我正在使用带有多个按钮的UI,我需要在按钮点击时启动后台任务,并在任务完成时向主线程+更新UI报告。
目前这是我的代码的一部分:
private void button1Click(object sender, EventArgs e)
{
button1.Text = "Starting";
button1.Enabled = false;
button1Worker.RunWorkerAsync();
}
private void button1worker_DoWork(object sender, DoWorkEventArgs e)
{
toolStarter.startTool("button1");
}
private void button1worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button1.Text = "Autoruns";
button1.Enabled = true;
}
此解决方案按预期/预期工作,但是对于15个不同的按钮重复相同的代码,这对我来说似乎是错误的。
你能推荐一些其他方法来做同样的事情吗?
我确实尝试了ThreadPool
队列,但在任务完成后无法更新UI。
答案 0 :(得分:2)
您可以通过async / await来实现,这样可以简化代码并消除对后台工作人员的需求:
private async void button1Click(object sender, EventArgs e)
{
button1.Text = "Starting";
button1.Enabled = false;
await Task.Run(() => toolStarter.startTool("button1"));
button1.Text = "Autoruns";
button1.Enabled = true;
}
如果您的按钮都在执行相同的操作,只更改了字符串,您可以重构它以支持:
private async Task ExecuteButton(Button button, string toolName)
{
button.Text = "Starting";
button.Enabled = false;
await Task.Run(() => toolStarter.startTool(toolName));
button.Text = "Autoruns";
button.Enabled = true;
}
private async void button1Click(object sender, EventArgs e)
{
await ExecuteButton(button1, "button1");
// Do any other specific stuff for after here
}
// Use for other buttons as needed
private async void button2Click(object sender, EventArgs e)
{
await ExecuteButton(button2, "button2");
}
答案 1 :(得分:0)
// This is your helper class that actually does the work
public class ToolStarter
{
public void startTool(string name)
{
// Put your switch statement here to decide what work to do
}
}
public class ButtonWorker
{
private Button button;
private ToolStarter toolStarter;
public ButtonWorker(Button button, ToolStarter toolStarter)
{
this.button = button;
this.toolStarter = toolStarter;
this.button.Enabled = false;
this.button.Text = "Starting";
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));
}
private void DoWork(object state)
{
this.toolStarter.startTool(button.Name);
// Pass control back to the UI thread so you can update your
// button text and enabled/status
this.button.Invoke(new Action(() =>
{
this.button.Text = "Autoruns";
this.button.Enabled = true;
}));
}
}
// This is just showing you how to use the ButtonWorker
public class ButtonWorkerTest
{
public ButtonWorkerTest()
{
var btn1 = new Button { Name = "button1" };
var btn2 = new Button { Name = "button2" };
var toolstarter = new ToolStarter(); // This is your class
var worker1 = new ButtonWorker(btn1, toolstarter);
var worker2 = new ButtonWorker(btn2, toolstarter);
}
}