访问在运行时创建的任何后台工作者

时间:2013-09-03 08:52:01

标签: c# .net multithreading winforms backgroundworker

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

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

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

//代码:

'点击事件

         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");

        }
    }

如何访问先前创建的backgroundworker实例并检查进程状态并显示该等内容?

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

这可能吗?

4 个答案:

答案 0 :(得分:2)

您可以在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并运行存储的下一个任务。

答案 1 :(得分:1)

您可以使用Tag的{​​{1}}属性:

DataGridViewRow

所以你可以访问它。

答案 2 :(得分:1)

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

 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作为网格行的行标识符。

希望有所帮助。

答案 3 :(得分:0)

嗯,这很容易。将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();
         }
}