C#非UI线程弹窗,详细案例
时间: 2024-09-09 11:01:40 浏览: 27
在C#中,当我们在非用户界面(Non-UI)线程中执行可能会阻塞用户界面的操作,如长时间运行的计算或网络请求时,为了避免主线程被阻塞导致应用程序无响应,通常需要在后台线程(Background Thread)中完成这些任务,并使用专门的方式来更新UI。Windows Forms应用中最常见的做法是使用`BackgroundWorker`类,而WPF则可以使用`Task`和`Dispatcher`。
**详细案例 - 使用BackgroundWorker (Windows Forms)**
```csharp
private void btnStart_Click(object sender, EventArgs e)
{
// 创建一个新的BackgroundWorker实例
BackgroundWorker worker = new BackgroundWorker();
// 设置工作完成后的操作(这里是异步显示消息)
worker.DoWork += (sender2, args) =>
{
for (int i = 0; i < 10; i++)
{
// 模拟耗时操作,这里只是一个示例
Thread.Sleep(500);
// 在DoWork事件中直接修改UI会出错,因此通过ProgressChanged发送消息
if (worker.CancellationPending)
break;
args.ReportProgress(i);
}
};
// 当进度改变时更新UI
worker.ProgressChanged += (sender2, args) =>
{
progressBar.Value = args.ProgressPercentage;
};
// 开始工作并设置取消按钮的行为
worker.WorkerSupportsCancellation = true;
worker.RunWorkerAsync();
// 显示取消按钮
btnCancel.Visible = true;
}
private void btnCancel_Click(object sender, EventArgs e)
{
// 如果工作正在进行,尝试取消它
if (!worker.IsBusy)
return;
worker.CancelAsync();
}
```
**详细案例 - 使用Task (WPF)**
```csharp
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
// 创建异步任务
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
// 阻塞操作
await Task.Delay(500);
// 更新UI在Dispatcher上下文内
Dispatcher.Invoke(new Action(() => progressBar.Value = i));
}
// 取消任务
Application.Current.Dispatcher.InvokeShutdown();
});
// 显示取消按钮
btnCancel.Visibility = Visibility.Visible;
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
// 如果任务还在运行,尝试取消
if (Application.Current.Dispatcher.HasThreadAccess)
Application.Current.Dispatcher.InvokeShutdown();
}
```