System.InvalidOperationException: '視窗控制代碼建立後才能呼叫控制項上的 Invoke 或 BeginInvoke的解决方法是什么,请给出代码示例
时间: 2024-04-14 16:26:04 浏览: 217
控件异步调用的Control.BeginInvoke实例解析源码
4星 · 用户满意度95%
当你在非UI线程上尝试使用 Invoke 或 BeginInvoke 方法时,可能会出现 "視窗控制代碼建立後才能呼叫控制項上的 Invoke 或 BeginInvoke" 异常。这是因为这些方法只能在创建相应控件的UI线程上调用。
为了解决这个问题,你可以使用 SynchronizationContext 类来在非UI线程上执行UI操作。下面是一个示例代码,展示了如何使用 SynchronizationContext 来解决这个问题:
```csharp
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
public class Program
{
private static ProgressBar progressBar;
private static SynchronizationContext synchronizationContext;
public static void Main()
{
Form form = new Form();
progressBar = new ProgressBar();
form.Controls.Add(progressBar);
synchronizationContext = SynchronizationContext.Current;
// 创建一个线程来模拟任务的进度更新
Thread thread = new Thread(UpdateProgress);
thread.Start();
// 显示窗体
Application.Run(form);
}
private static void UpdateProgress()
{
for (int i = 0; i <= 100; i++)
{
// 使用 SynchronizationContext.Post 方法在 UI 线程上执行更新操作
synchronizationContext.Post(new SendOrPostCallback(state =>
{
progressBar.Value = (int)state;
}), i);
// 模拟任务的延迟
Thread.Sleep(100);
}
}
}
```
在上述代码中,我们通过在 Main 方法中获取当前的 SynchronizationContext 对象来捕获UI线程的上下文。然后,在 UpdateProgress 方法中,我们使用 SynchronizationContext 的 Post 方法来在UI线程上执行进度更新操作。这样就可以避免在非UI线程上使用 Invoke 或 BeginInvoke 方法时出现异常。
通过这种方式,你可以在非UI线程上安全地更新UI控件的值,而无需直接使用 Invoke 或 BeginInvoke 方法。注意,这种方法也适用于使用 Task 或其他异步操作的情况。
希望这个代码示例能帮助你解决 "視窗控制代碼建立後才能呼叫控制項上的 Invoke 或 BeginInvoke" 异常。
阅读全文