Общаться между двумя потоками - PullRequest
0 голосов
/ 17 ноября 2010

У меня есть что-то подобное. Это дает мне ошибку. Я вырезал все ненужные части кода. Это дает мне эту ошибку

The calling thread cannot access this object because a different thread owns it.

 public partial class MainWindow : Window
{
    BackgroundWorker worker;
    Grafik MainGrafik;

    double ProgressBar
    {
        set { this.progressBarMain.Value = value; }
    }

    public MainWindow()
    {
        InitializeComponent();
        worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);

        MainGrafik = new Grafik();
        MainGrafik.ProgressUpdate += 
            new Grafik.ProgressUpdateDelegate(MainGrafik_ProgressUpdate);

        worker.RunWorkerAsync();
    }

    void MainGrafik_ProgressUpdate(double progress)
    {
        ProgressBar = progress;
    }


    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        while(true)
        {
            MainGrafik.Refresh();
            Thread.Sleep(2000);
        }
    }
}

class Grafik
{
    public delegate void ProgressUpdateDelegate(double progress, 
        DateTime currTime);
    public event ProgressUpdateDelegate ProgressUpdate;

    public void Refresh()
    {
            ProgressUpdate(5); // Just for testing
    }
}

Ответы [ 3 ]

8 голосов
/ 17 ноября 2010

Вы не можете обновить объекты пользовательского интерфейса из другого потока. Они должны быть обновлены в потоке пользовательского интерфейса. Попробуйте добавить этот код в MainGrafik_ProgressUpdate (двойной прогресс)

void MainGragfik_ProgressUpdate(double progress)
{
    if (InvokeRequired)
    {
         BeginInvoke((MethodIvoker)(() =>
         {
             MainGragfik_ProgressUpdate(progress);
         }));

         return;
    }

    ProgressBar = progress;
}
0 голосов
/ 17 ноября 2010

коротко вызовите это в форме в контексте выполнения вашего другого потока:

  void MainGrafik_ProgressUpdate(object sender, EventArgs e) { 
  Action<T> yourAction =>() yourAction;            

   if(yourForm.InvokeRequired)
        yourForm.Invoke(yourAction);
   else yourAction;

  }

Или с MethodInvoker (пустой делегат)

 void MainGrafik_ProgressUpdate(object sender, EventArgs e) { 
     MethodInvoker invoker = delegate(object sender, EventArgs e) {

        this.ProgressBar = whatever progress;
  };        


  }
0 голосов
/ 17 ноября 2010

Поток, запускающий событие ProgressUpdate, является вашим BackgroundWorker. Обработчики событий ProgressUpdate, скорее всего, работают в этом потоке, а не в потоке пользовательского интерфейса.

...