C# 异步 this.BeginInvoke 、`Task.Run` 或 `Thread`
需要更新UI,则用 this.BeginInvoke
this.BeginInvoke(new Action(() =>
{
GetUserList();
}));
不需要更新UI,则可以用异步线程
Task.Run(() => GetUserList(););
1. 外部代码本身就在 UI 线程中运行
- 如果你在 UI 线程中调用
this.BeginInvoke,那么BeginInvoke会将委托放入 UI 线程的消息队列中,但由于当前已经是 UI 线程,BeginInvoke的委托仍然会在 UI 线程中执行。 - 因此,外部代码和
GetUserList()的线程 ID 会相同。
验证方法:
检查外部代码是否在 UI 线程中运行。例如:
Console.WriteLine("外部代码是否在 UI 线程中: " + this.InvokeRequired);
- 如果
InvokeRequired为false,说明当前代码已经在 UI 线程中运行。
2. BeginInvoke 的行为
BeginInvoke是异步的,但它仍然会将委托调度到 UI 线程中执行。- 如果外部代码已经在 UI 线程中运行,
BeginInvoke的委托会立即执行(或稍后执行,取决于消息队列的状态),但仍然在同一个线程中。
3. 代码执行顺序
- 如果外部代码和
BeginInvoke的委托都在 UI 线程中运行,它们的线程 ID 会相同。 - 即使
BeginInvoke是异步的,它仍然会在 UI 线程中执行,因此线程 ID 不会改变。
如何验证 BeginInvoke 的异步行为?
如果你想验证 BeginInvoke 的异步行为,可以尝试以下方法:
示例代码:
using System;
using System.Threading;
using System.Windows.Forms;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Button_Click(object sender, EventArgs e)
{
// 打印外部代码的线程 ID
Console.WriteLine("外部线程 ID: " + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("外部代码是否在 UI 线程中: " + this.InvokeRequired);
// 使用 BeginInvoke 异步执行
this.BeginInvoke(new Action(() =>
{
// 打印 GetUserList 的线程 ID
Console.WriteLine("GetUserList 线程 ID: " + Thread.CurrentThread.ManagedThreadId);
GetUserList();
}));
// 模拟外部代码继续执行
Console.WriteLine("外部代码继续执行...");
}
private void GetUserList()
{
// 模拟方法执行
Console.WriteLine("GetUserList 正在执行...");
}
}
可能的输出:
如果外部代码在 UI 线程中运行,输出可能如下:
外部线程 ID: 1
外部代码是否在 UI 线程中: False
外部代码继续执行...
GetUserList 线程 ID: 1
GetUserList 正在执行...
如果外部代码在非 UI 线程中运行,输出可能如下:
外部线程 ID: 10
外部代码是否在 UI 线程中: True
外部代码继续执行...
GetUserList 线程 ID: 1
GetUserList 正在执行...
总结:
- 如果外部代码和
GetUserList()的线程 ID 相同,说明它们运行在同一个线程中(通常是 UI 线程)。 - 如果你想验证
BeginInvoke的异步行为,可以确保外部代码在非 UI 线程中运行(例如使用Task.Run或Thread)。 - 使用
InvokeRequired可以检查当前代码是否在 UI 线程中运行。
如果你希望 GetUserList() 在另一个线程中运行,而不是在 UI 线程中,可以考虑使用 Task.Run 或其他多线程技术。例如:
Task.Run(() => GetUserList());
本文来自博客园,作者:VipSoft 转载请注明原文链接:https://www.cnblogs.com/vipsoft/p/18744676
浙公网安备 33010602011771号