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