Передача аргументов между потоками с использованием делегатов - C#

Узнай цену своей работы

Формулировка задачи:

Правильно ли я понимаю что делегат будет вызван в том потоке в котором я его создал, а не в том в котором я его вызываю? У меня проблем с передачей данных между потоками с использованием делегатов. Мне нужно вызвать метод из созданного мною потока "DirtyJob" в основном потоке. Пытался это реализовать используя делегаты. В чем ошибка? Помогите исправить Logo.cs:
Листинг программы
  1. ...
  2. internal DirtyJob MyDirtyJob = new DirtyJob();
  3. // #1 Создал делегат в основном потоке:
  4. public Logo()
  5. {
  6. InitializeComponent();
  7. MyDirtyJob.UpdateProgress += new UpdateProgressEvent(DirtyJob_UpdateProgress);
  8. }
  9. // Обновление информации на диалоговом окне
  10. private void DirtyJob_UpdateProgress(ProgressEventArgs e)
  11. {
  12. // #4 Тут происходит исключение
  13. // Cross-thread operation not valid: Control 'LabelProgressMessage' accessed from a thread other than the thread it was created on.
  14. // При этом в "Потоки" почему то указан не основной поток в качестве потока в котором сработала точка останова(исключение), а поток "DirtyJob"
  15. LabelProgressMessage.Text = e.Message;
  16. }
  17. private void Logo_Load(object sender, EventArgs e)
  18. {
  19. MyDirtyJob.StartJob();
  20. }
  21. ...
DirtyJob.cs:
Листинг программы
  1. ...
  2. // Класс для передачи аргументов между потоками
  3. public class ProgressEventArgs
  4. {
  5. public ProgressEventArgs(int Progress, string Message)
  6. {
  7. _Progress = Progress;
  8. _Message = Message;
  9. }
  10. private volatile int _Progress;
  11. private volatile string _Message;
  12. public int Progress
  13. {
  14. get
  15. {
  16. return _Progress;
  17. }
  18. }
  19. public string Message
  20. {
  21. get
  22. {
  23. return _Message;
  24. }
  25. }
  26. }
  27. public delegate void UpdateProgressEvent(ProgressEventArgs e);
  28. public class DirtyJob
  29. {
  30. public event UpdateProgressEvent UpdateProgress;
  31. public void StartJob()
  32. {
  33. // Это работает!
  34. UpdateProgress(new ProgressEventArgs(0, "Запуск"));
  35. // #2 Создал и запустил новый поток:
  36. Thread DirtyJobThread = new Thread(DoWork);
  37. DirtyJobThread.Name = "DirtyJob";
  38. DirtyJobThread.Start(this);
  39. }
  40. private void DoWork(object sender)
  41. {
  42. DirtyJob WorkThread = (DirtyJob)sender;
  43. // #3 Это приводит к исключению
  44. UpdateProgress(new ProgressEventArgs(1, "Проверка обновлений"));
  45. }
  46. }
  47. ...
п.с. Используя BackgroundWorker все прекрасно работает, но он мне не подходит и нужно обойтись без него!
Решил проблему завернув тело функции DirtyJob_UpdateProgress в BeginInvoke, но что мне делать когда объект метод которого я хочу вызвать не будет иметь никакого отношения к System.Windows.Forms?
Листинг программы
  1. private void DirtyJob_UpdateProgress(ProgressEventArgs e)
  2. {
  3. BeginInvoke(new Action(() =>
  4. {
  5. ShowButtonTimer.Stop();
  6. ShowButtonTimer.Start();
  7. CommonProgressBar.Value = e.Progress;
  8. LabelProgressMessage.Text = e.Message;
  9. }));
  10. }

Решение задачи: «Передача аргументов между потоками с использованием делегатов»

textual
Листинг программы
  1. using System;
  2. using System.Windows.Forms;
  3.  
  4. namespace WindowsFormsProgressReporting
  5. {
  6.     public partial class Form1 : Form
  7.     {
  8.         DirtyJob MyDirtyJob;
  9.  
  10.         public Form1()
  11.         {
  12.             InitializeComponent();
  13.  
  14.             // вариант 1
  15.             //Progress<ProgressEventArgs> progress = new Progress<ProgressEventArgs>(DirtyJob_UpdateProgress);
  16.             //MyDirtyJob = new DirtyJob(progress);
  17.  
  18.             // вариант 2
  19.             //MyDirtyJob = new DirtyJob(DirtyJob_UpdateProgress);
  20.  
  21.             // вариант 3
  22.             MyDirtyJob = new DirtyJob();
  23.             MyDirtyJob.Progress.ProgressChanged += Progress_ProgressChanged;
  24.         }
  25.  
  26.         private void Progress_ProgressChanged(object sender, ProgressEventArgs e)
  27.         {
  28.             label1.Text = e.Message;
  29.         }
  30.  
  31.         private void DirtyJob_UpdateProgress(ProgressEventArgs e)
  32.         {
  33.             label1.Text = e.Message;
  34.         }
  35.  
  36.         private void Form1_Load(object sender, EventArgs e)
  37.         {
  38.             MyDirtyJob.StartJob();
  39.         }
  40.     }
  41. }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

5   голосов , оценка 3.8 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут