Передача аргументов между потоками с использованием делегатов - 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(); } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д