C#异步调用实例小结

顾言
顾言
发布时间:2026-10-13| 5人浏览过
原创

C#中的异步调用是实现非阻塞操作、提升应用程序(尤其是GUI应用)响应速度的关键手段。本文通过一个包含耗时操作的模拟场景,依次演示了从传统同步到现代异步模式的五种具体实现方式,包括直接使用EndInvoke、利用WaitHandle阻塞等待、轮询检测完成状态以及在后台运行结束后自动触发回调。

准备条件:定义异步处理方法

为了演示各种异步调用模式,我们需要一个模拟耗时操作的测试方法,并定义对应的委托类型。以下代码展示了这一基础结构:

using System;
using System.Threading;
// 其他引用...

public string LongRunningMethod(int iCallTime, out int iExecThread)
{
    // 模拟耗时操作,如网络请求或复杂计算
    Thread.Sleep(iCallTime);
    // 获取当前执行线程的ID,用于验证是否跨线程
    iExecThread = AppDomain.GetCurrentThreadId();
    return "MyCallTime was " + iCallTime.ToString();
}

// 定义与LongRunningMethod签名匹配的委托
delegate string MethodDelegate(int iCallTime, out int iExecThread);

模式一:同步调用

这是最基础的调用方式。主线程发起调用后会一直阻塞,直到方法执行完毕才继续向下运行。虽然简单,但在处理耗时任务时会卡死界面。

public void DemoSyncCall()
{
    string s;
    int iExecThread;
    MethodDelegate dlgt = new MethodDelegate(this.LongRunningMethod);
    
    // 同步调用,线程在此处挂起3秒
    s = dlgt(3000, out iExecThread);
    MessageBox.Show(string.Format(
        "The delegate call returned the string: {0}, and the thread ID {1}", 
        s, iExecThread.ToString()));
}

模式二:直接异步调用 (EndInvoke)

此模式通过 BeginInvoke 启动异步操作,主线程可以继续执行其他逻辑。最后通过 EndInvoke 获取结果。如果主线程在执行完自己的逻辑前就调用 EndInvoke,它也会发生阻塞,直到异步操作完成。

public void DemoEndInvoke()
{
    MethodDelegate dlgt = new MethodDelegate(this.LongRunningMethod);
    string s;
    int iExecThread;
    
    // 启动异步调用
    IAsyncResult ar = dlgt.BeginInvoke(5000, out iExecThread, null, null);
    
    // TODO: 在此处执行主线程的其他有用工作
    // ...
    // 获取结果。如果此时异步尚未完成,主线程将在此处等待
    s = dlgt.EndInvoke(out iExecThread, ar);
    MessageBox.Show(string.Format(
        "The delegate call returned the string: {0}, and the number {1}", 
        s, iExecThread.ToString()));
}

模式三:使用 WaitHandle 等待

类似于 EndInvoke 模式,但显式地通过 IAsyncResult.AsyncWaitHandle 来判断异步操作是否完成。这在需要更精细控制等待行为时非常有用。

public void DemoWaitHandle()
{
    string s;
    int iExecThread;
    MethodDelegate dlgt = new MethodDelegate(this.LongRunningMethod);
    
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);
    
    // 等待异步操作完成的信号
    ar.AsyncWaitHandle.WaitOne();
    
    s = dlgt.EndInvoke(out iExecThread, ar);
    MessageBox.Show(string.Format(
        "The delegate call returned the string: {0}, and the number {1}", 
        s, iExecThread.ToString()));
}

模式四:轮询调用模式

主线程不被动等待,而是主动周期性地检查 IAsyncResult.IsCompleted 属性。这种方式适合那些可以间歇性执行的工作流,但需要注意避免高频轮询导致CPU占用过高。

public void DemoPolling()
{
    MethodDelegate dlgt = new MethodDelegate(this.LongRunningMethod);
    string s;
    int iExecThread;
    
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);
    
    // 轮询检查完成状态
    while (ar.IsCompleted == false)
    {
        Thread.Sleep(10); // 短暂休眠以模拟其他工作并降低CPU负载
    }
    
    s = dlgt.EndInvoke(out iExecThread, ar);
    MessageBox.Show(string.Format(
        "The delegate call returned the string: {0}, and the number {1}", 
        s, iExecThread.ToString()));
}

模式五:回调通知模式

这是最解耦的异步处理方式。我们不需要在主线程中显式调用 EndInvoke,而是传入一个回调函数 (AsyncCallback)。当后台任务结束时,系统会自动在线程池线程中执行该回调,并在回调内部获取最终结果。

public void DemoCallback()
{
    MethodDelegate dlgt = new MethodDelegate(this.LongRunningMethod);
    int iExecThread;
    
    // 创建回调委托
    AsyncCallback cb = new AsyncCallback(MyAsyncCallback);
    
    // 将原始委托作为 asyncState 传入,以便在回调中能重新获取委托实例
    IAsyncResult ar = dlgt.BeginInvoke(5000, out iExecThread, cb, dlgt);
}

// 回调方法:在异步操作完成后由线程池线程调用
public void MyAsyncCallback(IAsyncResult ar)
{
    string s;
    int iExecThread;
    
    // 从 AsyncState 取出原始的委托对象
    MethodDelegate dlgt = (MethodDelegate)ar.AsyncState;
    
    // 在回调中获取结果
    s = dlgt.EndInvoke(out iExecThread, ar);
    MessageBox.Show(String.Format(
        "The delegate call returned the string: {0}, and the number {1}", 
        s, iExecThread.ToString()));
}

总结

上述五种模式涵盖了C#早期异步编程的主要技术路线。在现代开发中,对于GUI应用,回调模式和直接EndInvoke能有效避免界面卡顿;而在服务器端开发中,通常建议升级到基于 async/await 的任务并行库(TPL)以获得更清晰的代码结构。以上就是C#异步调用实例小结的详细内容,更多关于C#并发编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。