TTimer i baza danych

0

Robię prowizoryczny "czat" dla graczy. Najpierw kod.

Timer1, Interval = 1000:

msg.close;
msg.sql.clear;
msg.sql.add('SELECT * FROM game_chat WHERE id > 0');
msg.open;

while not msg.Eof do begin
   almemo1.Lines.Add('['+msg.fieldbyname('author').asstring+'] '+msg.fieldbyname('text').asstring);
          del_msg.close;
          del_msg.SQL.clear;
          del_msg.SQL.add('DELETE FROM game_chat WHERE id='''+msg.fieldbyname('id').asstring+''';');
          del_msg.ExecSQL;
              msg.Next;

Objasnienie:

  1. Pobieranie wiadomosci
  2. Wyswietlanie
  3. Usuwanie pobranej wiadomosci

Wysyłanie wiadomości:

chat.close;
  chat.sql.Clear;
  chat.sql.Add('INSERT INTO game_chat (author, text) VALUES ('''+author+''', '''+text+''')');
  chat.execsql;
  aledit1.Clear;

msg, del_msg, chat to komponenty TADQuery (AnyDac components)

Mój problem polega na tym, że przy testowaniu z kolegą tego czata, niektóre wiadomości - teoretycznie wysyłało, lecz ich nie pokazywało. Prawdopodobnie były od razu kasowane. Drugim problemem jest to, że przy wstawieniu w Timer1 więcej instrukcji - aplikacja się po prostu zawiesza.

Chodzi mi o sposób na wydajniejsze i mniej "stresujące" korzystanie z czatu, bez obaw, ze jakas wiadomosc nie dojdzie, badz aplikacja sie zawiesi przy tak prostych czynnosciach.

Wiem, że sposób na moje wyswietlanie wiadomosci jest zly, bo przy duzej liczbie uzytkownikow cala ta zabawka zacznie wariowac, dlatego proszę was o pomoc, o naprowadzenie na "wlasciwa droge" ...

0

dodatkowa tabela do której zapiszesz kto którą wiadomośc przeczytał i przy pobieraniu filtrujesz i nie wyświetlasz danej osobie już wyświetlonych wiadomości.
Usuwanie (fizyczne) to bardzo zły pomysł

BTW czat oparty o BD (bez serwera) to niezbyt dobre rozwiązanie

0

A ta tabela jak miałaby wyglądać ?

Id - Odbiorca - Wiadomosc - czy_przeczytane ?

Imo to jeszcze bardziej obciazy baze ..

BTW czat oparty o BD (bez serwera) to niezbyt dobre rozwiązanie

Więc jak inaczej to zrobić ? Jak bez serwera ?

0

źle przeczytałeś - czat oparty o BD (bez dedykowanego programu, który będzie zarządzał połączeniami i wiadomościami ) to niezbyt dobre rozwiązanie

BD powinna być tylko dodatkiem do przechowywania archiwalnych wiadomości i/lub wiadomości do klientów, którzy w chwili ich wysłania nie są podpięci. Wszystkie wiadomości adresowane do podpiętych klientów powinny do nich trafiać bez pośrednika w postaci BD

0

To jak już mnie naprowadzasz, powiedz, co zrobić, by ten pieprzony (za przeproszeniem) Timer tak nie zamulał aplikacji ?
Przy tak prostym kodzie z Intervalem = 1000

procedure TForm3.Timer1Timer(Sender: TObject);
var
ident: integer;
begin
msg.close;
msg.sql.clear;
msg.sql.add('SELECT * FROM game_chat WHERE id > 0 ORDER BY id ASC');
msg.open;

while not msg.Eof do begin
   del_msg.Close;
   del_msg.sql.Clear;
   del_msg.sql.add('SELECT * FROM game_chat_read WHERE character_name='''+character_name.Caption+''' and msg_id='''+inttostr(msg.fieldbyname('id').asinteger)+''';');
   del_msg.Open;
   ident := msg.fieldbyname('id').asinteger;
    if del_msg.RowsAffected = 0 then begin
        almemo1.Lines.add('['+msg.fieldbyname('author').AsString+'] '+msg.fieldbyname('text').asstring);
        del_msg.close;
        del_msg.SQL.Clear;
        del_msg.sql.add('INSERT INTO game_chat_read (character_name, msg_id) VALUES ('''+character_name.Caption+''', '''+inttostr(ident)+''')');
        del_msg.ExecSQL;
    end;
   msg.Next;
end;
end;

Tak aplikacje zamula (powt.), ze z kolega nie moglem normalnie rozmawiac...

0

wywołujesz to co sekundę +- to myślisz, że jak to będzie działać??
Trzeba by zacząć od optymalizacji struktury bazy, potem wsadzić większość tych dziwnych zapytań w procedury składowe, żeby nie ciągnąć niepotrzebnie danych po sieci, zoptymalizować sam serwer BD itd

0

Właśnie pomyślałem o serwerze, przez który beda wykonywane zapytania do bazy, i przez serwer beda plynely wyniki zapytan. Sęk w tym, ze nie wiem, na jakiej zasadzie mialoby to dzialac ? Przez sockety wysylac zapytania i odsylac do klienta ?

0
Micidami napisał(a)

Tak aplikacje zamula (powt.), ze z kolega nie moglem normalnie rozmawiac...

Daj po msg.Next Application.ProcessMessages ;)
Pierwsze co powinieneś zrobić to zastąpić Timer wątkiem.
Na tym etapie możesz sobie spokojnie darować bzdety typu optymalizacja bazy, procki składowe, dedykowany serwer na socketach, itd..

Narzekanie na Timer nie ma większego sensu z definicji, bo OnTimer zawsze jest wykonywane w ramach głównego wątku.

0
SiNuS napisał(a)

Na tym etapie możesz sobie spokojnie darować bzdety typu optymalizacja bazy, procki składowe, dedykowany serwer na socketach, itd..

ROTFL, pewnie lapiej się wziąć za szydełkowanie...

0

Spróbowałem z tymi wątki - po raz pierwszy w zyciu, korzystajac z art. o wątkach w tym serwisie.

Wątek:

TCzat = class(TThread)
  public
  procedure getonline;
  procedure Execute;
  end;

Var:

var
  Form3: TForm3;
  Czat: TCzat;

Pobieranie userów online:

procedure TCzat.getonline;
begin
with form3 do begin
login.close;
    login.SQL.clear;
    login.sql.Add('SELECT * FROM game_login_in WHERE id > 0 ORDER by id DESC');
    login.open;
      while not login.Eof do begin
      allistbox1.items.clear;
      allistbox1.Items.add(form3.login.fieldbyname('logged').AsString);
      login.Next;
      end;
    application.ProcessMessages;

    sleep(1000);
    end;
end;

Na sam koniec:

initialization
  Czat := TCzat.Create(True);
end.

Lecz nie pobiera tych userów. ALListBox1 jest czysty.

0

A co masz w metodzie Execute?

0

Przykazania: ;)

  1. Wątek powinien mieć swój komplet komponentów bazodanowych.
  2. Aktualizacja kontrolek VCL przez Synchronize()
  3. Wywal Application.ProcessMessages
  4. póki co tyle ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1