Wywołanie metody na głównym wątku - Dispatcher

0

Cześć, chcę wywołać kod z wątku głównego, będąc w wątku pobocznym. Znalazłem, że jest taka klasa Dispatcher, więc próbowałem ją ogarnąć:

Forma główna aplikacji:

 
Dispatcher m_mainThreadDispatcher;

public MainForm()
{
    InitializeComponent();
    m_mainThreadDispatcher = Dispatcher.CurrentDispatcher;
}

//i metoda pomocnicza do wywoływania kodu na głównym wątku:
public void ExecuteInApplicationContext(Action action)
{
    if (Thread.CurrentThread != m_mainThreadDispatcher.Thread)
        m_mainThreadDispatcher.Invoke(action, null);
    else
        action.Invoke();
}

I chciałem tego użyć w taki sposób:

 
void DoWorkInThread()
{
    Thread th = new Thread(new ThreadStart(ThreadDoWork));
    th.Name = "TypingThread";
    th.Priority = ThreadPriority.Normal;

    th.Start();
//nie mogę zrobić th.Join, bo mam formę z progressem operacji
}

void ThreadDoWork()
{
    DoTheWork(); //tutaj leci całe zadanie do wykonania

//jak zadanie się wykona, to ma się wykonać kod na głównym wątku
    ((MainForm)Application.Forms[0]).ExecuteInApplicationContext(
        new Action(
            () =>
                {
                     DoSomeWorkInMainThread();
                }
        )
    );
}

I problem jest taki, że ExecuteInApplicationContext się wywołuje, ale już DoSomeWorkInMainThread się nie wykonuje. Gdzie jest problem?

0
public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
      }

      void DoWorkInThread()
      {
         Thread th = new Thread(ThreadDoWork);
         th.Name = "TypingThread";
         th.Priority = ThreadPriority.Normal;
         th.Start();
      }

      void ThreadDoWork()
      {
         DoTheWork();
         BeginInvoke(new DoSomeWorkInMainThreadDelegate(DoSomeWorkInMainThread));
      }

      private void DoSomeWorkInMainThread()
      {
         Debug.WriteLine("Start => DoSomeWorkInMainThread");
         Thread.Sleep(200);
         Debug.WriteLine("End => DoSomeWorkInMainThread");
      }

      private void DoTheWork()
      {
         Debug.WriteLine("Start => DoTheWork");
         Thread.Sleep(200);
         Debug.WriteLine("End => DoTheWork");
      }

      private void button1_Click(object sender, EventArgs e)
      {
         DoWorkInThread();
      }

      delegate void DoSomeWorkInMainThreadDelegate();
   }

WorkThread.PNG
MainThread.PNG

0
Juhas napisał(a):

I problem jest taki, że ExecuteInApplicationContext się wywołuje, ale już DoSomeWorkInMainThread się nie wykonuje. Gdzie jest problem?

Po czym stwierdzasz że się nie wykonuje? Pamiętaj że zanim zostanie wywołany dispatcher może trochę "czasu" minąć. Nie dzieje się to instrukcja po linijce z dispatcherem. Breakpoint prawdę Ci powie/pokaże.

0

I jak? Tutaj też nikt nie wie?

0

Spróbuj czegoś takiego:

void ThreadDoWork()
{
DoTheWork(); //tutaj leci całe zadanie do wykonania

Dispatcher.Invoke(() =>
{
//Tutaj wywołaj swoją metodę.
});
}

0

Niestety, dalej nic

0

Podeślij swój cały przykład. Gdzieś musi być mały błąd bo takie rozwiązanie powinno działać :)

0

No, niczego więcej niż to, co podesłałem nie mogę, bo to projekt z wieloma plikami, a to, co podesłałem jest całkowicie związane. Ale tak, jest coś dziwnego, bo żaden Invoke mi nie idzie tam. Nie mam pojęcia dlaczego. Czy locki mogą mieć coś z tym wspólnego? W sensie:

 
lock(myLock)
{
//
}

Okazało się, że jedyne, co zadziałało, to:

 
th.Start(); //to jest wątek
while(th.IsAlive)
{
  Application.DoEvents();
  Thread.Sleep(100);
}
0

Metodę DoWorkInThread() wywołujesz z wątku głównego?

Zakomentuj wszytko co masz w DoSomeWorkInMainThread() i wstaw tam jakieś Console.WriteLine("DoSomeWorkInMainThread - Test"). I zobacz czy po uruchomieniu coś wywala w konsolę.

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