Передача аргументов между потоками с использованием делегатов - C#
Формулировка задачи:
Правильно ли я понимаю что делегат будет вызван в том потоке в котором я его создал, а не в том в котором я его вызываю? У меня проблем с передачей данных между потоками с использованием делегатов.
Мне нужно вызвать метод из созданного мною потока "DirtyJob" в основном потоке.
Пытался это реализовать используя делегаты.
В чем ошибка? Помогите исправить
Logo.cs:
DirtyJob.cs:
п.с.
Используя BackgroundWorker все прекрасно работает, но он мне не подходит и нужно обойтись без него!
...
internal DirtyJob MyDirtyJob = new DirtyJob();
// #1 Создал делегат в основном потоке:
public Logo()
{
InitializeComponent();
MyDirtyJob.UpdateProgress += new UpdateProgressEvent(DirtyJob_UpdateProgress);
}
// Обновление информации на диалоговом окне
private void DirtyJob_UpdateProgress(ProgressEventArgs e)
{
// #4 Тут происходит исключение
// Cross-thread operation not valid: Control 'LabelProgressMessage' accessed from a thread other than the thread it was created on.
// При этом в "Потоки" почему то указан не основной поток в качестве потока в котором сработала точка останова(исключение), а поток "DirtyJob"
LabelProgressMessage.Text = e.Message;
}
private void Logo_Load(object sender, EventArgs e)
{
MyDirtyJob.StartJob();
}
......
// Класс для передачи аргументов между потоками
public class ProgressEventArgs
{
public ProgressEventArgs(int Progress, string Message)
{
_Progress = Progress;
_Message = Message;
}
private volatile int _Progress;
private volatile string _Message;
public int Progress
{
get
{
return _Progress;
}
}
public string Message
{
get
{
return _Message;
}
}
}
public delegate void UpdateProgressEvent(ProgressEventArgs e);
public class DirtyJob
{
public event UpdateProgressEvent UpdateProgress;
public void StartJob()
{
// Это работает!
UpdateProgress(new ProgressEventArgs(0, "Запуск"));
// #2 Создал и запустил новый поток:
Thread DirtyJobThread = new Thread(DoWork);
DirtyJobThread.Name = "DirtyJob";
DirtyJobThread.Start(this);
}
private void DoWork(object sender)
{
DirtyJob WorkThread = (DirtyJob)sender;
// #3 Это приводит к исключению
UpdateProgress(new ProgressEventArgs(1, "Проверка обновлений"));
}
}
...
Решил проблему завернув тело функции DirtyJob_UpdateProgress в BeginInvoke, но что мне делать когда объект метод которого я хочу вызвать не будет иметь никакого отношения к System.Windows.Forms?
private void DirtyJob_UpdateProgress(ProgressEventArgs e)
{
BeginInvoke(new Action(() =>
{
ShowButtonTimer.Stop();
ShowButtonTimer.Start();
CommonProgressBar.Value = e.Progress;
LabelProgressMessage.Text = e.Message;
}));
}Решение задачи: «Передача аргументов между потоками с использованием делегатов»
textual
Листинг программы
using System;
using System.Windows.Forms;
namespace WindowsFormsProgressReporting
{
public partial class Form1 : Form
{
DirtyJob MyDirtyJob;
public Form1()
{
InitializeComponent();
// вариант 1
//Progress<ProgressEventArgs> progress = new Progress<ProgressEventArgs>(DirtyJob_UpdateProgress);
//MyDirtyJob = new DirtyJob(progress);
// вариант 2
//MyDirtyJob = new DirtyJob(DirtyJob_UpdateProgress);
// вариант 3
MyDirtyJob = new DirtyJob();
MyDirtyJob.Progress.ProgressChanged += Progress_ProgressChanged;
}
private void Progress_ProgressChanged(object sender, ProgressEventArgs e)
{
label1.Text = e.Message;
}
private void DirtyJob_UpdateProgress(ProgressEventArgs e)
{
label1.Text = e.Message;
}
private void Form1_Load(object sender, EventArgs e)
{
MyDirtyJob.StartJob();
}
}
}