C# 访问在运行时创建的任何后台工作程序
场景:我的应用程序中有一个C# 访问在运行时创建的任何后台工作程序,c#,.net,multithreading,winforms,backgroundworker,C#,.net,Multithreading,Winforms,Backgroundworker,场景:我的应用程序中有一个DataGrid,其中onclicking每行的值都填充在下面的文本框中。我将更新这些值,当单击“保存”时,该过程将花费更多时间来完成 因此,我编写了一个backgroundworker,使流程异步运行。当剪切每一行时,将创建backgroundworker的实例,并完成该过程。在更新过程中,用户将选择网格的第二行并更新该值。因此,这将创建另一个实例,进程将在后台运行 现在,当两个更新进程都在运行时,如果用户选择了网格的第一行,则应该有一条消息显示“进程仍在运行” //
DataGrid
,其中onclicking
每行的值都填充在下面的文本框中。我将更新这些值,当单击“保存”时,该过程将花费更多时间来完成
因此,我编写了一个backgroundworker,使流程异步运行。当剪切每一行时,将创建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");
}
}
public void SaveDetails()
{
对于(int i=0;i<10;i++)
{
系统线程线程睡眠(5000);
MessageBox.Show(“Hi”);
}
}
如何访问先前创建的backgroundworker实例,检查流程的状态并显示消息
注意:可能有多个进程同时运行,因此我应该能够访问任何进程
这可能吗?嗯,那很容易。将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();
}
}
您可以在列表中存储您创建的任何BackgroundWorker
以随时引用它们,但也可以创建任务队列
并在那里存储任何挂起的流程,因此您在任何时候都只有一个BackgroundWorker
将后台工作人员存储在列表中
例如,创建一个列表(BackgroundWorker)
,可以在代码中的任何地方访问该列表。每次创建新的BackgroundWorker
,都将其添加到列表中
:
mylist.Add(bw)
您可以使用许多选项来访问正确的backgroundworker
。最简单的方法是创建自己的类,该类将有一个标识符(例如,DataGrid
的行)和backgroundworker
。这样,您的列表
将属于此类,而不是后台工作人员
:
myClass.BackgroundWorkerProperty = bw
myClass.id = myId
myList.Add(myClass)
使用队列运行任务
创建一个具有运行任务信息的类型的队列
。例如,DataGrid
的行,如果足够,则类型为Integer
(索引),然后每次运行backgroundworker
时添加它:
myQueue.Add(myRow)
每次backgroundworker
完成时,检查队列
,并运行存储的下一个任务 您可以使用DataGridViewRow的标记属性:
var bw = new BackgroundWorker();
row.Tag = bw;
因此,您可以访问它。如果您使用的是.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.");
}
}
}
公共部分类表单1:表单
{
List taskList=新列表();
公共表格1()
{
初始化组件();
}
私有异步无效按钮1\u单击(对象发送方,事件参数e)
{
Task=Task.Run(()=>SaveDetails());
Show(task.Id+“已启动”);
任务列表。添加(任务);
var issucess=等待任务;
}
公共bool SaveDetails()
{
对于(int i=0;i<10;i++)
{
系统线程线程睡眠(5000);
//MessageBox.Show(“Finishing”);
}
返回true;
}
私有无效按钮2\u单击(对象发送者,事件参数e)
{
foreach(任务列表中的var任务)
{
如果(task.IsCompleted==true)
MessageBox.Show(task.Id+“已完成”);
}
}
}
我已经创建了第二个按钮单击事件来访问和显示当前完成的所有任务。
另外,请注意,您可以使用task.Id
作为网格行的行标识符
希望这能有所帮助。我如何知道particluar background运行的是哪一行?我需要像第一次更新一样访问此后台实例正在运行,第二次更新此实例和上…@SanthoshKumar我会创建一个字典,从一点到BackgroundWorker。你需要一个例子吗?我想到了这个主意。但没能成功。你能发布一个示例代码吗?其中我需要确保为网格的行映射了正确的实例(值正在更新)。哪一个?创建队列
以按顺序运行所有流程,或将所有BackgroundWorker
存储在列表
中。列表和队列中应该存储哪些值?希望第一种方法(列表)对我的应用程序适用。因为这是一个大问题,让我尝试和张贴,如果我有问题。