Asynchroniczne delegacje oraz timer

0

Mam asynchroniczną delegację która włącza podany program i czeka aż on się zakończy. Mam również Timer'a który robi screenshot'y. Nie wiem dlaczego ale jak wywołam rfp.Waitforexit(Int32.MaxValue); (piszę z pamięci) to to zatrzymuję mi także Timer'a który jako część głównego wątku powinien ciągle chodzić ponieważ asynchroniczna delegacja pozwala na działanie dwóch thread'ów naraz.

Proszę o pomoc.

Dodatkowe Info: Program w rfp włącza się poprawnie i cały kodzik jest dobrze wywoływany lecz tylko te screenshot'y nie działają. Dostaję jeszcze taki komunikat w debugerze jak dojdę do końca skryptu w delegacji gdzie mam waitforexit wstawione.

Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.

1

Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.

Wątek może się odwoływać tylko do kontrolek w którym jest wywoływany. Było z milion razy (chociaż możliwe też że nie rozumiem problemu)

0

Komunikat już naprawiłem... Wsadziłem te kontrolki co potrzebowałem do delegacji i chodzi ok ale mniejsza z tym...

Chodzi mi oto czemu moja Asynchroniczna Delegacja zatrzymuję Timer'a i kod w nim.

0

Ej, no ale przecież jak wywołasz WaitForExit w głownym wątku aplikacji to przecież on(ten wątek) się zatrzyma. I bedzie czekał aż wywołany proces sie zakonczy.
Przykładowo Forma nie będzie się przerysowywać. Więc jesli timer ma za zadanie cos rysowac/ wyswietlać to nie bedziesz tego widział, pomimo ze timer działa dalej.

0

Mam waitforexit w asychronicznej delegacji która jest jako drugi wątek a timer'a mam w głównym wątku umieszczone i ciągle nie chodzi... O co tutaj chodzi.

W delegacji mam waitforexit. W wątku głównym mam kod do timer'a 1 i wszystkie kontrolki do których on się odwołuję.

0

Wyślij kod, prościej będzie wyłapać o co chodzi.

0

sorki ale kodu nie mogę bo to duży projekt... dam ci kodzik delegacji na email

0

Daj tutaj, wieksza szansa że ktoś Ci pomoże.

0
delegate void DelegatCzekający();

        private void ABC()
        {
            while (true)
            {
                if (skończone) break;
                else continue;
            }
        }

        private void Wywołaj()
        {
            DelegatCzekający delegat = Czekanie;
            delegat.BeginInvoke(Callback, this);
        }

        private void Czekanie()
        {
            System.Diagnostics.Process rfp = new System.Diagnostics.Process();
            rfp.StartInfo = new System.Diagnostics.ProcessStartInfo(process_path);
            rfp.Start();
            rfp.WaitForExit(Int32.MaxValue);

            if (rfp.HasExited == true)
            {
                TextWriter tw1 = File.AppendText(FilePathLog);
                tw1.WriteLine("Czas końca grania: " + DateTime.Now);
                tw1.Close();
                this.DelegateUpload(this, null);
                               
            }
        }

        private void Callback(IAsyncResult res)
        {
            skończone = true;
            
        }

        private void DelegateUpload(object sender, EventArgs e)
        {
            try
            {
                this.CheckFTPAddress(this, null);
                Application.DoEvents();
                FTPFolder = nick + "_" + email + "_" + hardwareID;

                DelegateMakeDir(FTPFolder);

                string path1 = FilePath;
                string start = path1;
                DirectoryInfo dir1 = new DirectoryInfo(start);
                FileInfo[] pliki = dir1.GetFiles("*.jpeg");
                foreach (FileInfo file in pliki)
                {

                    string fullName = file.Name;
                    uploadFile(m_FTPAddress + FTPFolder + "/", path1 + fullName, Username, Password);
                    file.Delete();

                }
                string path2 = FilePath;
                string start2 = path2;
                DirectoryInfo dir2 = new DirectoryInfo(start);
                FileInfo[] pliki2 = dir1.GetFiles("*.txt");
                foreach (FileInfo file2 in pliki2)
                {

                    string fullName = file2.Name;
                    uploadFile(m_FTPAddress + FTPFolder + "/", path2 + fullName, Username, Password);
                    file2.Delete();

                }

                string path12 = System.Environment.CurrentDirectory.ToString() + "\\main\\";
                string start12 = path12;
                DirectoryInfo dir12 = new DirectoryInfo(start12);
                FileInfo[] pliki12 = dir12.GetFiles("*.cfg");

                foreach (FileInfo file12 in pliki12)
                {
                    string fullName12 = file12.Name;
                    uploadFile(m_FTPAddress + FTPFolder + "/", path12 + fullName12, Username, Password);
                }
                this.Close();
            }
            catch
            {

            }

        }
        private void DelegateMakeDir(string dirName)
        {
            FtpWebRequest reqFTP;
            try
            {
                // dirName = name of the directory to create.
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(m_FTPAddress + "/" + dirName));
                reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(Username, Password);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();

                ftpStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
            }
        }
            
        }        
0

Tak się nie zagłębiając. Domyślam się ze Timer ma robić screenshoty uruchomionej aplikacji, tutaj nigdzie go nie włączasz?
Jeszcze GetResponse klasy FTPWeb moze zablokować wątek, ale to chyba nie powod. Chociaz moze byc powodem ze pliki sie nie uploaduja czy co tam się robić ma.

0

pliki zapisują się do folderu na kompie a potem dopiero jak app się wyłączy to je wysyła wątek delegate...

0

Te asynchroniczne wywołanie delegata, nie powinno blokować timera, więc problem jest gdzieś indziej, apost wcześniej chodziło mi że nigdzie nie startujesz timera, musisz go wywołać. Może startujesz go jeszcze gdzie indziej, ale tutaj tego nie widać. W każdym razie, tutaj nie ma nic co mogło by blokować "inne" wątki programu, przykładowo na jakim chodzi timer.

0

Timer jest cały czas włączony od start'u

0

Stworzyłem coś podobnego działającego na bazie Twojego projektu i wszystko jest OK. (oczywiscie bez wysylania na serwer)

        delegate void DelegatCzekający();
        bool skończone = false;

        private void Wywołaj()
        {
            DelegatCzekający delegat = Czekanie;
            delegat.BeginInvoke(Callback, this);
        }

        private void Czekanie()
        {
            System.Diagnostics.Process rfp = new System.Diagnostics.Process();
            rfp.StartInfo = new System.Diagnostics.ProcessStartInfo(@"C:\WINDOWS\System32\calc.exe");
            rfp.Start();
            rfp.WaitForExit();

            if (rfp.HasExited == true)
            {
                MessageBox.Show("Czas końca grania: " + DateTime.Now);
                //this.DelegateUpload(this, null);
            }
        }

        private void Callback(IAsyncResult res)
        {
            skończone = true;
            timer1.Stop();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Wywołaj();
            timer1.Start();
        }
        int x;
        private void timer1_Tick(object sender, EventArgs e)
        {
            Bitmap b = new Bitmap(300, 300);
            Graphics g = Graphics.FromImage(b);

            g.CopyFromScreen(0, 0, 0, 0, new Size(300, 300), CopyPixelOperation.SourceCopy);

            b.Save(@"C:\APO\" + x.ToString() + ".bmp");
            x++;
        }
0

czyli jak screeny będą w delegacji umieszczone to będzie ok??

0

Ale tutaj nie ma screenów w delegacji, delegat ktorego wywołujesz asynchronicznie, bierze wątek z PoolThread-a i w nim wywołana jest metoda czekanie. (Chyba jakoś tak ;P) CallBack zostanie wywołany jak wykonanie metody dobiegnie konca.
Screeny są robione timerem. Ja w kodzie wyzej nie zrobiłem nic wiecej niż Ty miałeś. Tylko napisałem sam tykanie dla timera i go wywołałem.

PS.
Nie wiedziałem Twojego Timera, i nie wiem jak robisz te screenshoty

0

podobnie jak ty tylko jeszcze zmienjszam jakość i dodaje watermark ale wszystko odwołuje się do timer1_tick... screeny dobrze chodzą jak app nie jest włączony (i waitforexit nie chodzi)

0

może to jest wina gry pełnoekranowej. Próbowałeś na innych aplikacjach, jak chociazby kalkulator, saper? czy cokolwiek co nie ma trybu wyłączności pełny ekran?

0

tak i nie chodzi... daj mi twój gg to jutro coś się pokombinuje ok... dzięx

0

wie ktoś może jak to rozwiązać bo ciągle mam ten sam problem.

0

na podstawie tego co zamiesciles chyba nie da sie go rozwiazac. problem jest gdzies indziej. Jesli chcesz aby ktos Ci pomogl to wyslij caly projekt. Jesli nie tutaj to mozesz mi wyslac na email, jak znajde powod to Cie powiadomie.

0

mógł byś wejść na gg (moje to 4875993) i na teamviewer bym ci pokazał bo nie mogę kodu rozsyłać... sorki

1

Dodam że kiedyś miałem podobny dziwaczny problem z timerem - po wykonaniu jakiejś operacji, (chyba zmiany obrazka w pictureBoxie ale głowy nie dam) wstrzymywało mi Timera.

W końcu nie ma programu bez błędów, a visual studio, CSC, CLR czy co tam jest winne pewnie nie jest wyjątkiem.

Oczywiście nie twierdzę że twój problem nie ma rozwiązania, tylko wspominam że miałem kiedyś podobnie dziwny problem ;)

0

metoda ABC zawadzała... już naprawiłem dzięki Dark_Astray... Ta metoda zatrzymywała całe gui bo warunek się nie zgadzał... nie wiem jakie to miało powiązanie z gui jak to było w asynchronicznej delegacji ale już tego nie wywołuję i działa ok...

0

W przypadku kolegi wyżej, w jednym momecie zostawała uruchamiana pętla while, i wtedy tykanie timera przestawało działać.

tak myslalem trochę, ale nie wiem czy do dobrego rozwiązania doszedłem. Timer.Tick to jest event -> musi zostac wysłana wiadomość o zajściu zdarzenia
A skoro główny wątek aplikacji jest zatrzymany -> wiadomości nie są tłumaczone -> czekaja w kolejce -> zdarzenie tick nie jest wywoływane.

Jeśli jestem w błędzie, popraw ktoś :)

1

Skoro działa to czym się przejmować? :D
Chociaż wydawało mi się że timer liczy w osobnym (jeszcze) wątku... Ale patrz wyżej :)

0

Działa, ale ciekawy jest powód nie działania.
Tak, działa na innym wątku, ale przegląd wiadomości jest bazowo jeden.
I to wygląda tak jakby, główny wątek aplikacji wysyłał wiadomość o zdarzeniu tick, i dopiero wtedy timer zaczyna jakąś tam operację juz na swoim wątku. A jak aplikacja nie jest w stanie wyslac wiadomości, jest zablokowana czyms inntm, to na nic nam timer.

//q: tak, mniej wiecej tak to wyglada, moze nie tyle główny wątek aplikacji, co wątek okna które posiada komponent timer. jesli uzywa sie watkow/timerow, nigdy nie wilno zapomniec o starym dobrym messagepump i o tym, ze wszystko co "asynchroniczne" czy "invokowane" tak naprawde jest realizowane przez cos w rodzaju starych win32 msg + petli wiadomosci utrzymywanej przez watki okien niemodalnych

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