C# 在使用委托运行后台工作时,如何处理控件启用/禁用选项?
在按钮点击事件中,我有一个需要很长时间的查询。所以我在BackgroundWorker上运行它C# 在使用委托运行后台工作时,如何处理控件启用/禁用选项?,c#,.net,delegates,C#,.net,Delegates,在按钮点击事件中,我有一个需要很长时间的查询。所以我在BackgroundWorker上运行它 private void btnGenerate_Click(object sender, EventArgs e) { btnGenerate.Enabled = false; BackgroundWorker worker = new BackgroundWorker(); worker.DoWork
private void btnGenerate_Click(object sender, EventArgs e)
{
btnGenerate.Enabled = false;
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate (object s, DoWorkEventArgs args)
{
Data = DataLoader.GetData(Environment.UserName); // stored procedure execution
if (Data != null)
{
GenerateExcel(Data);
GenerateSingleExcel(Data);
}
};
worker.RunWorkerCompleted += delegate (object s, RunWorkerCompletedEventArgs args)
{
progressBar1.Visible = false;// ProgressBarStyle.Marquee
btnGenerate.Enabled = true;
};
worker.RunWorkerAsync();
}
我的问题是,我需要设置
btnGenerate.Enable=false
点击按钮。并在执行完成后启用
我在Runworker里试过了,已经完成了,但正在展示
'跨线程操作无效:从创建控件的线程以外的线程访问控件'btnGenerate'
任何建议都会有帮助。您的主要问题是BackgroundWorker的事件是在工作线程上执行的,而不是在UI线程上执行的。但是UI元素只能从UI线程访问 为了解决这个问题,我建议使用async/await而不是BackgroundWorker: 如果DataLoader提供了异步GetDataAsync,那么您就不需要Task.Run了 如果由于任何原因无法实现异步,则RunWorkerCompleted处理程序应使用Invoke或:
我认为更好的方法是Data=wait Task.Run=>{var Data=…;…return Data;},以避免数据属性上的多线程问题。
// declare as async
private async void btnGenerate_Click(object sender, EventArgs e)
{
btnGenerate.Enabled = false;
Data = await Task.Run(() => {
var data = DataLoader.GetData(Environment.UserName); // stored procedure execution
if (data != null)
{
GenerateExcel(Data);
GenerateSingleExcel(Data);
}
return data; // as suggested by Vlad, don't set Data on this thread
});
// this is now executed back on the UI thread
progressBar1.Visible = false;// ProgressBarStyle.Marquee
btnGenerate.Enabled = true;
}
worker.RunWorkerCompleted += OnRunWorkerCompleted;
//...
public void OnRunWorkerCompleted(object s, RunWorkerCompletedEventArgs args)
{
if (InvokeRequired)
{
// not on the UI thread - use (Begin-)Invoke
BeginInvoke(new RunWorkerCompletedEventHandler(OnRunWorkerCompleted), s, args);
return;
}
// now we're on the UI thread
progressBar1.Visible = false;// ProgressBarStyle.Marquee
btnGenerate.Enabled = true;
}