CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Restart

Restart

dział ogólny

Re: Restart

Nowy postprzez polymorphism » niedziela, 27 grudnia 2009, 18:23

Kopia powinna czekać na zakończenie pierwszego programu i dopiero potem przejść do dalszych instrukcji, tak się jednak nie dzieje. Kopia pomija funkcję: WaitForSingleObject(hMutex, INFINITE) i przechodzi do dalszych instrukcji kończąc działanie programu.
Dlaczego???

Pisałem dlaczego. Kopia nie pomija WaitForSingleObject, tylko funkcja ta nie ma na co czekać, wszak pierwsza instancja aplikacji stworzyła muteks, ale nie jest jego właścicielem.



Jeśli chodzi o przykład, to niby działa, ale w sumie nie wiadomo czy poprawnie. Daj po wywołaniu kopi Sleep(5000), coby było wiadomo, że kopia czeka na zamknięcie aplikacji.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Restart

Nowy postprzez Cyfrowy Baron » niedziela, 27 grudnia 2009, 19:00

Pisałem dlaczego. Kopia nie pomija WaitForSingleObject, tylko funkcja ta nie ma na co czekać, wszak pierwsza instancja aplikacji stworzyła muteks, ale nie jest jego właścicielem.


Przeczytaj mój ostatni post. Nie o to chodzi.

W przypadku restartu funkcja WaitForSingleObject ma na co czekać, gdyż jest wywoływana w kopii programu wiec jest procesem potomnym, oczekuje na zamknięcie aplikacji, która wywołała kopię i po zakończeniu oczekiwania przechodzi do dalszych instrukcji. Problem w tym, że wychodzi z warunku pomijając kod znajdujący się po tej funkcji.
To powinno być jednak na odwrót, czyli program główny powinien czekać na zakończenie działania programu potomnego, a jest odwrotnie.

W przypadku gdy kopia jest uruchamiana ręcznie (nie restart), wtedy funkcja WaitForSingleObject nie ma na co czekać, więc od razu przechodzi do dalszych instrukcji.

Dlatego działanie jest prawidłowe i działa, niejasna jest sytuacja z tym kodem w pierwszym przypadku:

Kod: Zaznacz cały
ShowMessage("Program jest już uruchomiony");
Application->Terminate();




Daj po wywołaniu kopi Sleep(5000), coby było wiadomo, że kopia czeka na zamknięcie aplikacji.


No i po tym, program działa jak powinien, czyli nie działa prawidłowo.

W tej sytuacji nie widzę zastosowania dla funkcji WaitForSingleObject.

Rzecz w tym, że restart programu nie wymaga wcale takich zabiegów, wystarczy taki kod:

Kod: Zaznacz cały
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ShellExecute(NULL,"open","restartAppMutex.exe",NULL,NULL,SW_SHOW);
Close();
}
//---------------------------------------------------------------------------


Program uruchamia swoją kopie i kończy działanie. Czego więcej potrzeba?!

Upierając się przy mutexach, można to zrobić tak:

plik nagłówkowy np. Unit1.h:
Kod: Zaznacz cały
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:   // IDE-managed Components
    TButton *Button1;
    TEdit *Edit1;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall FormCreate(TObject *Sender);
private:   // User declarations
    void __fastcall WmCopyData(TWMCopyData& Message);
public:      // User declarations
    __fastcall TForm1(TComponent* Owner);

BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_COPYDATA, TWMCopyData, WmCopyData)
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


plik źródłowy np. Unit1.cpp:
Kod: Zaznacz cały
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
ShellExecute(NULL,"open","restartAppMutex.exe",NULL,NULL,SW_SHOW);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WmCopyData(TWMCopyData& Message)
{
AnsiString slCmdLine = (char*)Message.CopyDataStruct->lpData;

if(slCmdLine == "close") Close();

}
//---------------------------------------------------------------------------


plik źródłowy projektu, np. Project1.cpp:
Kod: Zaznacz cały
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    try
    {
      HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, "twoja_aplikacja.exe_restart");

      if(!hMutex) hMutex = CreateMutex(0, 0, "twoja_aplikacja.exe_restart");
      else
      {
        HWND hWnd = FindWindow("TForm1", NULL);

        if(hWnd)
        {
          char cmdLine[] = "close";
          COPYDATASTRUCT cds;
          cds.cbData = strlen(cmdLine) + 1;
          cds.lpData = cmdLine;
       
          SendMessage(hWnd, WM_COPYDATA, 0, (LPARAM)&cds);
        }
      }

         Application->Initialize();
         SetApplicationMainFormOnTaskBar(Application, true);
         Application->CreateForm(__classid(TForm1), &Form1);
         Application->Run();
         
     ReleaseMutex(hMutex);
    }
    catch (Exception &exception)
    {
         Application->ShowException(&exception);
    }
    catch (...)
    {
         try
         {
             throw Exception("");
         }
         catch (Exception &exception)
         {
             Application->ShowException(&exception);
         }
    }
    return 0;
}
//---------------------------------------------------------------------------


Ten kod oczywiście w przypadku, gdy zostanie uruchomiona ręcznie kopia programu spowoduje zamknięcie istniejącego programu i uruchomienie kopii, ale można by to dopracować, np. poprzez wywołanie restartu programu z przekazaniem argumentu z linii komend, potem kopia pobiera ten argument i przekazuje go do działającego programu, który odbiera ten argument i kończy działanie. Uruchomiona ręcznie kopia programu nie zawierała by argumentu, więc pierwszy program nie otrzymując niezbędnego argumentu nie kończył by działania, kopia programu nie mając argumentu sama kończyła by działanie. Do tego wszystkiego chyba wogóle nie potrzebny byłby mutex. To wszystko jednak niepotrzebnie skomplikowałoby program, więc Twój sposób jest lepszy.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Restart

Nowy postprzez polymorphism » niedziela, 27 grudnia 2009, 20:06

W tej sytuacji nie widzę zastosowania dla funkcji WaitForSingleObject.

Bez tej funkcji użycie muteksów (do synchronizacji) mija się z celem. Ona musi być, jeśli chcesz coś zsynchronizować procesy za pomocą muteksów, inaczej się nie da.

Rzecz w tym, że restart programu nie wymaga wcale takich zabiegów

Tu nie ma reguły. Choć podejrzewam, że pitkowi3010 wersja bez muteksów w pełni wystarczy.

Do tego wszystkiego chyba wogóle nie potrzebny byłby mutex.

Dokładnie ;) Cały mechanizm oparty jest o komunikat WM_COPYDATA.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Restart

Nowy postprzez Pitek » niedziela, 27 grudnia 2009, 23:07

Niezmiernie wam Panowie dziękuję ! Nie wiem jak moge się odwidzieńczyć hmm może kiedyś kiedy posiądę większoą wiedzę :)
Mam tylko jedno ale mianowicie podałem kod w poim wcześniejszym poście który sprawdza czy dokonano zmian jeżeli tak to przy zamykaniu programu pyta czy napewno go zamknąć bez zapisu a z kodem do restaru programu to sie kopie. Wyświetla się to zapytanie czy zapisać oraz że nie można uruchomić kopii programu bo mam tą blokade na muteksie z poradnika ze strony i nie wiem jak to wyprostować.
Komputer służy do tego aby ułatwić Ci pracę, której bez niego w ogóle byś nie miał.
E.Murphy
http://piotrekprogramy.pl
Avatar użytkownika
Pitek
Kreacjusz
Kreacjusz
 
Posty: 290
Dołączył(a): środa, 14 października 2009, 14:53
Lokalizacja: Rybnik/Wrocław
Podziękował : 43
Otrzymał podziękowań: 5
System operacyjny: Win 7 Ultimate 64bit SP1 / Ubuntu 19.04 LTS 64bit
Kompilator: Embarcadero RAD Studio XE2
SKYPE: pitek3010
Gadu Gadu: 7060047
    NieznanyNieznana

Re: Restart

Nowy postprzez Cyfrowy Baron » poniedziałek, 28 grudnia 2009, 10:55

W tej sytuacji musisz usunąć ten kod ze zdarzenia OnClose i przenieść go do restartu, ale jeszcze lepiej jest go uzależnić od restartu, czyli gdy zostanie naciśnięty przycisk Restart zmienia się stan zmiennej typu bolean (bool) na true informując program, że zamykany będzie z restartem, tym samym program wywoła zapytanie o zapis zmian nie ze zdarzenia OnClose lecz z restartu. Program na starcie ustawi wartość zmiennej bolean na false, jeżeli restart nie zostanie wywołany to nie zmieni się również stan tej zmiennej, a tym samym zostanie wywołane zapytanie o zapis ze zdarzenia OnClose. Zapytanie o zapis i sam zapis najepiej jest umieścić w odrębnej funkcji by nie powtarzać kodu:

w pliku nagłówkowym np. Unit1.h
Kod: Zaznacz cały
private:
        bool SaveOnClose(TObject *Sender); // funkcja zapisująca zmiany przy zamknięciu
        bool restart; // zmienna sterująca 


w pliku źródłowym np. Unit1.cpp
Kod: Zaznacz cały
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
  restart = false;
}
//---------------------------------------------------------------------------
bool TForm1::SaveOnClose(TObject *Sender) // funkcja zapisująca zmiany przy zamknięciu
{
    if(modify == true)
    {
       int mbResult2 = MessageBox(NULL, "Dokonano zmian. Czy chcesz zapisać swoją pracę?", "Zakończ", MB_YESNOCANCEL | MB_ICONQUESTION);

       if(mbResult2 == IDNO) return true;

       if(mbResult2 == IDCANCEL) return false;

       if(mbResult2 == IDYES)
      {
         MessageBox(NULL,"Aby zapisać dotychczasowy efekt pracy użyj funkcji Zapisz w lewym dolnym rogu okna programu.", "Zakończ", MB_OK | MB_ICONINFORMATION);

         return false;
      }
   }

  return true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) // RESTART PROGRAMU
{
  restart = true;
  if(SaveOnClose(Sender))
  {
       HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,"twoja_aplikacja.exe_restart");
       if(hEvent)
       {
           ShellExecute(NULL,"open","restartApp.exe",NULL,NULL,SW_SHOW);
           static signal_event_at_end tmp(hEvent);
           Close();
       }
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if(restart == false)
{
  switch(SaveOnClose(Sender))
  {
   case true:  Action = caFree; return;
   case false: Action = caNone; return;
   default:    Action = caFree;
  }
}
}
//---------------------------------------------------------------------------


To to samo co masz Ty, tylko zoptymalizowane.



Mała uwaga odnośnie tego kodu:

Kod: Zaznacz cały
  if(mbResult2 == IDYES)
  {
    MessageBox(NULL,"Aby zapisać dotychczasowy efekt pracy użyj funkcji Zapisz w lewym dolnym rogu okna programu.", "Zakończ", MB_OK | MB_ICONINFORMATION);

    return false;
  }


Treść komunikatu sugeruje, że zapis jest wykonywany w jakimś zdarzeniu, być może OnClick dla przycisku lub OnClick dla MenuItem, to bez znaczenia, gdyż zamiast komunikatu znacznie lepiej jest wykorzystać tutaj polimorfizm, czyli odwołać sie bezpośrednio do tego zdarzenia. Załóżmy, że przycisk lub MenuItem w którym jest realizowany zapis nosi nazwę Zapisz1, wtedy ten fragment kodu mógłby wyglądać tak:

Kod: Zaznacz cały
  if(mbResult2 == IDYES)
  {
    Zapisz1Click(Sender);
    MessageBox(NULL, "Zapisano zmiany.", "Nazwa programu - zamykanie", MB_OK | MB_ICONINFORMATION);

    return true;
  }


Tak jest bardziej profesjonalnie, program sam zapisuje zmiany zamiast nakazywać to użytkownikowi. Takie nieustanne zasypywanie użytkownika komunikatami, może go zirytować, szczególnie gdy program może wykonać to zadanie.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Restart

Nowy postprzez Pitek » poniedziałek, 28 grudnia 2009, 13:32

Bardzo za wszystko dziękuję !
Jeżeli chodzi o ten ostatni kod z poprzedniego postu to nie moge wywołać tego kloknięcia ponieważ użytkownik wcześniej musi podać nazwę pliku dlatego taki komunikat :)
Jeszcze raz Dziękuję !!!
Komputer służy do tego aby ułatwić Ci pracę, której bez niego w ogóle byś nie miał.
E.Murphy
http://piotrekprogramy.pl
Avatar użytkownika
Pitek
Kreacjusz
Kreacjusz
 
Posty: 290
Dołączył(a): środa, 14 października 2009, 14:53
Lokalizacja: Rybnik/Wrocław
Podziękował : 43
Otrzymał podziękowań: 5
System operacyjny: Win 7 Ultimate 64bit SP1 / Ubuntu 19.04 LTS 64bit
Kompilator: Embarcadero RAD Studio XE2
SKYPE: pitek3010
Gadu Gadu: 7060047
    NieznanyNieznana

Re: Restart

Nowy postprzez Pitek » sobota, 2 stycznia 2010, 21:57

Pojawił mi się błąd :
Kod: Zaznacz cały
[BCC32 Error] Unit1.cpp(4427): E2141 Declaration syntax error

I odnośi mi się do jest lini :
Kod: Zaznacz cały
static signal_event_at_end tmp(hEvent);

Cała funkcja gdzie występuje błąd :
Kod: Zaznacz cały
void __fastcall TForm1::Nowy2Click(TObject *Sender)
{
  restart = true;
  if(SaveOnClose(Sender))
  {
      HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,"Średnia Ważona.exe_restart");
      if(hEvent)
      {
         ShellExecute(NULL,"open","Średnia Ważona.exe",NULL,NULL,SW_SHOW);
         static signal_event_at_end tmp(hEvent);
         Close();
      }
  }
}
//---------------------------------------------------------------------------

Bardzo proszę o pomoc :roll:
Komputer służy do tego aby ułatwić Ci pracę, której bez niego w ogóle byś nie miał.
E.Murphy
http://piotrekprogramy.pl
Avatar użytkownika
Pitek
Kreacjusz
Kreacjusz
 
Posty: 290
Dołączył(a): środa, 14 października 2009, 14:53
Lokalizacja: Rybnik/Wrocław
Podziękował : 43
Otrzymał podziękowań: 5
System operacyjny: Win 7 Ultimate 64bit SP1 / Ubuntu 19.04 LTS 64bit
Kompilator: Embarcadero RAD Studio XE2
SKYPE: pitek3010
Gadu Gadu: 7060047
    NieznanyNieznana

Re: Restart

Nowy postprzez polymorphism » sobota, 2 stycznia 2010, 22:54

I odnośi mi się do jest lini :

Linia jest poprawna, być może z definicją klasy signal_event_at_end jest coś nie tak.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Restart

Nowy postprzez Pitek » sobota, 2 stycznia 2010, 22:56

Czyli co mam z tym zrobić ?
Komputer służy do tego aby ułatwić Ci pracę, której bez niego w ogóle byś nie miał.
E.Murphy
http://piotrekprogramy.pl
Avatar użytkownika
Pitek
Kreacjusz
Kreacjusz
 
Posty: 290
Dołączył(a): środa, 14 października 2009, 14:53
Lokalizacja: Rybnik/Wrocław
Podziękował : 43
Otrzymał podziękowań: 5
System operacyjny: Win 7 Ultimate 64bit SP1 / Ubuntu 19.04 LTS 64bit
Kompilator: Embarcadero RAD Studio XE2
SKYPE: pitek3010
Gadu Gadu: 7060047
    NieznanyNieznana

Re: Restart

Nowy postprzez Cyfrowy Baron » niedziela, 3 stycznia 2010, 09:51

Testowałem kod polymorphism w środowisku C++Builder 2010 i nie ma tam żadnego błędu, wszystko jest poprawne. Prawdopodobnie źle definiujesz klasę signal_event_at_end.
Umieść klasę w pliku nagłówkowym formularza, w którym wywołujesz restart aplikacji:

plik nagłówkowy np. Unit1.h
Kod: Zaznacz cały
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
/* klasa pomocnicza  */
class signal_event_at_end
{
    HANDLE m_event;
public:
    signal_event_at_end(HANDLE event)
    :m_event(event) {}
    ~signal_event_at_end()
    {
     if(!m_event)return;
     SetEvent(m_event);
     CloseHandle(m_event);
    }
};   

//==========================================================
class TForm1 : public TForm
{
__published:   // IDE-managed Components
    TButton *Button1;
    TButton *Button2;
    TButton *Button3;
    TButton *Button4;
    TButton *Button5;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall Button2Click(TObject *Sender);
    void __fastcall Button3Click(TObject *Sender);
    void __fastcall Button4Click(TObject *Sender);
    void __fastcall Button5Click(TObject *Sender);
private:   // User declarations
    bool SaveOnClose(TObject *Sender);
    bool restart;

    TButton *Przycisk[5];
   
public:      // User declarations
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


Jak widzisz klasa signal_event_at_end została umieszczona poza klasą formularza.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Restart

Nowy postprzez Pitek » niedziela, 3 stycznia 2010, 13:16

Faktycznie musiał wkraść mi się tam jakiś błąd teraz działa !
Bardzo dziękuję !
Komputer służy do tego aby ułatwić Ci pracę, której bez niego w ogóle byś nie miał.
E.Murphy
http://piotrekprogramy.pl
Avatar użytkownika
Pitek
Kreacjusz
Kreacjusz
 
Posty: 290
Dołączył(a): środa, 14 października 2009, 14:53
Lokalizacja: Rybnik/Wrocław
Podziękował : 43
Otrzymał podziękowań: 5
System operacyjny: Win 7 Ultimate 64bit SP1 / Ubuntu 19.04 LTS 64bit
Kompilator: Embarcadero RAD Studio XE2
SKYPE: pitek3010
Gadu Gadu: 7060047
    NieznanyNieznana

Re: Restart

Nowy postprzez Pitek » wtorek, 14 grudnia 2010, 00:47

Minął już jakiś czas od kiedy użyłem tej funkcji restartującej do ówczesnego programu. Teraz znów jej potrzebuję i niby wszystko jest ok ale pojawia mi się ostrzeżenie kompilatora o następującej treści :

[BCC32 Warning] Unit1.cpp(417): W8104 Local Static with constructor dangerous for multi-threaded apps
Full parser context
Unit1.cpp(403): parsing: void _fastcall TForm1::Uruchomkreatorkonfiguracji1Click(TObject *)


Używam takiej deklaracji w pliku nagłówkowym :

KOD cpp:     UKRYJ  
//---------------------------------------------------------------------------
/* klasa pomocnicza  */
class signal_event_at_end
{
    HANDLE m_event;
public:
    signal_event_at_end(HANDLE event)
    :m_event(event) {}
    ~signal_event_at_end()
    {
     if(!m_event)return;
     SetEvent(m_event);
     CloseHandle(m_event);
    }
};
//---------------------------------------------------------------------------


Oraz takiego kodu w zdarzeniu przycisku MainMenu:

KOD cpp:     UKRYJ  
String nazwa = ExtractFileName(Application->ExeName);

HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE, (nazwa+"_restart").t_str());
if(hEvent)
{
 ShellExecute(NULL,"open",(nazwa).t_str(),NULL,NULL,SW_SHOW);
 static signal_event_at_end tmp(hEvent);
 Close();
}
A błąd wg. kompilatora odnosi się do tej linijki :

KOD cpp:     UKRYJ  
 static signal_event_at_end tmp(hEvent);


Co robić ? Czy można to zignorować ? Chciałbym jednak wiedzieć dlaczego wtedy nic takiego się nie pokazywało i jak można to prawidłowo naprawić ?
Poza tym zdarzy się czasem że program się nie zrestartuje tylko zamknie dzieje się tak często wtedy gdy dokonam dowolną czynność np. kliknięcie na przycisk który otworzy okno nr.2 po czym je zamknę wtedy tak funkcja nie resetuje mi programu tylko go zamyka. Jeżeli od otwarcia programu nic nie robię tylko restartuje to jest ok. Czyli jeżeli wykonam jakąś czynność od otwarcie programu a przed jego restartem to restart nie działa tylko program się zamyka zależało by mi też na tm aby funkcja ta zawierała blokadę otwarcia kopii programu, dodam jeszcze że przed restartem Usuwam jeden plik komendą DeleteFile();
Komputer służy do tego aby ułatwić Ci pracę, której bez niego w ogóle byś nie miał.
E.Murphy
http://piotrekprogramy.pl
Avatar użytkownika
Pitek
Kreacjusz
Kreacjusz
 
Posty: 290
Dołączył(a): środa, 14 października 2009, 14:53
Lokalizacja: Rybnik/Wrocław
Podziękował : 43
Otrzymał podziękowań: 5
System operacyjny: Win 7 Ultimate 64bit SP1 / Ubuntu 19.04 LTS 64bit
Kompilator: Embarcadero RAD Studio XE2
SKYPE: pitek3010
Gadu Gadu: 7060047
    Windows XPFirefox

Re: Restart

Nowy postprzez Cyfrowy Baron » wtorek, 14 grudnia 2010, 10:16

U mnie ten kod nie zgłasza żadnego błędu, więc nie o wszystkim nam tutaj piszesz, a przynajmniej zataiłeś coś istotnego. Spróbuj tak:

KOD cpp:     UKRYJ  
signal_event_at_end tmp(hEvent);


bez static.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Restart

Nowy postprzez polymorphism » wtorek, 14 grudnia 2010, 11:45

A błąd wg. kompilatora odnosi się do tej linijki :

No przecież to nie jest błąd! To jest ostrzeżenie, które mówi, że przy takiej konstrukcji, czyli statycznym obiekcie danej klasy, zdefiniowanym lokalnie, może zajść sytuacja, że dwa (lub więcej) wątki mogą naraz wywołać konstruktor, co jest oczywiście niekorzystne, wszak wszystko dotyczy tego samego obiektu. Więc jeśli nie wywołujesz tej metody z kilku wątków, nie ma problemu, to Ciebie nie dotyczy.

Ale jeśli to ostrzeżenie Ci tak bardzo przeszkadza, można się go pozbyć w prosty sposób:
KOD cpp:     UKRYJ  
class signal_event_at_end
{
        HANDLE m_event;
public:
        signal_event_at_end() :m_event() {}
               
        void set(HANDLE event) { m_event = event; }
               
        ~signal_event_at_end()
        {
                if(!m_event)return;
                SetEvent(m_event);
                CloseHandle(m_event);
        }
};


/* gdzieś na początku pliku Unit1.cpp */

signal_event_at_end g_sigevt; //<--- obiekt globalny


...

ShellExecute(NULL,"open",(nazwa).t_str(),NULL,NULL,SW_SHOW);
g_sigevt.set(hEvent);
Close();
 


Cyfrowy Baron napisał(a):Spróbuj tak: (...) bez static.

Bez static to to w ogóle sensu nie ma.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Restart

Nowy postprzez Cyfrowy Baron » wtorek, 14 grudnia 2010, 12:33

Bez static to to w ogóle sensu nie ma.


Musi mieć sens, gdyż działa prawidłowo bez static.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Poprzednia stronaNastępna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 13 gości