【问题标题】:Access any background worker created in runtime访问在运行时创建的任何后台工作人员
【发布时间】:2013-09-03 08:52:01
【问题描述】:

场景:我的应用程序中有一个DataGrid,其中onclikcing 每行,值填充在下面的texboxes 中。我将更新这些值,当点击保存时,该过程需要更多时间才能完成。

所以我编写了一个后台工作程序来使进程运行asynchronously。当每一行被点击时,一个backgroundworker 的实例被创建并且该过程完成。在该更新期间,用户将选择网格的第二行并更新该值。所以这将创建另一个实例,并且该进程将在后台运行。

现在,如果用户选择网格的第一行,则当两个更新进程都在运行时,应该会显示一条消息,显示“进程仍在运行”。

//代码:

' OnClick 事件

         var bw = new BackgroundWorker();
          bw.WorkerReportsProgress = true;
          bw.DoWork += delegate {
              SaveDetails();
          };
          bw.RunWorkerCompleted += delegate {
              MessageBox.Show("Completed");
          };
          bw.RunWorkerAsync();

'保存方法

 public void SaveDetails()
    {
        for (int i = 0; i < 10;i++ )
        {
            System.Threading.Thread.Sleep(5000);
            MessageBox.Show("Hi");

        }
    }

如何访问之前创建的后台工作实例并检查进程状态并显示消息?

注意:可能有多个进程同时运行,所以我应该可以访问任何进程。

这可能吗?

【问题讨论】:

    标签: c# .net multithreading winforms backgroundworker


    【解决方案1】:

    您可以将您创建的任何BackgrounWorker 存储在List 中以随时引用它们,但或者您可以创建一个任务Queue 并在那里存储任何待处理的进程,因此您只有一个BackgroundWorker随时。

    将 BackgroundWorkers 存储在列表中

    创建一个List(Of BackgroundWorker),例如,您可以在代码中的任何位置访问它。每次创建新的BackgroundWorker 时,将其添加到List

    mylist.Add(bw)
    

    您有很多选项可以稍后访问正确的backgroundworker。最简单的方法是创建自己的类,该类将有一个标识符(例如DataGrid 的行)和backgroundworker。这样,您的 list 将属于此类,而不是 BackgroundWorkers

    myClass.BackgroundWorkerProperty = bw
    myClass.id = myId
    myList.Add(myClass)
    

    使用队列运行任务

    创建一个Queue,其类型包含运行任务的信息。例如DataGrid所在的行,如果够了,那就输入Integer(索引),然后每次backgroundworker运行时添加:

    myQueue.Add(myRow)
    

    每次backgroundworker 完成时,检查Queue 并运行存储的下一个任务。

    【讨论】:

    • 我想到了这个主意。但是来不及了。你可以发布一个示例代码吗?在其中我需要确保为网格的行映射了正确的实例(正在更新的值)。
    • 哪一个?创建一个Queue 以按顺序运行所有进程或将所有BackgroundWorkers 存储在List 中?
    • 两者。应该存储在列表和队列中的值是什么?
    • 希望第一种方法(列表)适用于我的应用程序。因为它是一个大的,如果我有问题,让我尝试发布。
    【解决方案2】:

    您可以使用DataGridViewRowTag 属性:

    var bw = new BackgroundWorker();
    row.Tag = bw;
    

    所以你可以访问它。

    【讨论】:

      【解决方案3】:

      如果您使用的是 .NET 4.5,我建议您使用 Async/Await 而不是后台线程来解决您的问题,因为它的编程风格简单高效,如下所示:

       public partial class Form1 : Form
          {
              List<Task<bool>> taskList = new List<Task<bool>>();
              public Form1()
              {
                  InitializeComponent();
              }
      
              private async void button1_Click(object sender, EventArgs e)
              {            
                  Task<bool> task = Task.Run(() => SaveDetails());
                  MessageBox.Show(task.Id + " started.");
                  taskList.Add(task);
                  var isSuccess = await task;
              }
              public bool SaveDetails()
              {
                  for (int i = 0; i < 10; i++)
                  {
                      System.Threading.Thread.Sleep(5000);
                      //MessageBox.Show("Finishing.");                
                  }
                  return true;
              }       
      
              private void button2_Click(object sender, EventArgs e)
              {            
                  foreach (var task in taskList)
                  {                
                      if (task.IsCompleted == true)
                          MessageBox.Show(task.Id + " Completed.");
                  }        
              }
          }
      

      我创建了第二个按钮单击事件来访问和显示所有当前完成的任务。 另外,请注意您可以使用task.Id 作为网格行的行标识符。

      希望对您有所帮助。

      【讨论】:

        【解决方案4】:

        嗯,这很容易。将BackgroundWorker 作为成员放入您的表单中,然后您就可以从任何地方访问它:

        BackgroundWorker bg;
        
        public Form1()
        {
            bg = new BackgroundWorker();
        }
        
        
        private void button1_Click(object sender, EventArgs e)
        {
                 if(bg.IsBusy)
                 {
                     // show the message
                 }
                 else
                 {
                      bw.WorkerReportsProgress = true;
                      bw.DoWork += delegate {
                         SaveDetails();
                      };
                      bw.RunWorkerCompleted += delegate {
                         MessageBox.Show("Completed");
                      };
                      bw.RunWorkerAsync();
                 }
        }
        

        【讨论】:

        • 我怎么知道特定背景正在运行哪一行?我需要像第一次更新一样访问这个后台实例正在运行,第二次更新这个实例和 on.....
        • @SanthoshKumar 我会创建一个字典,从 Point 到 BackgroundWorker。你需要一个例子吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多