C# 异步调用中使用回调方法

本文介绍了在.NET中如何使用异步回调方法进行线程管理。详细解释了回调方法的签名要求和工作原理,并提供了示例代码。同时讨论了回调方法与线程安全的关系,以及如何在异步调用中传递状态信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        在上篇文章提到了进行异步调用的时候,我们可以手动指定超时时间和阻塞时间,然后再调用委托的EndInvoke()方法得到我们要的结果。然而,如果我们想在进行异步调用的时候进行很好的管理得话,那使用完成回调方法将是一个不错的选择。

        一:回调方法的签名和工作机制
        1.回调方法必须要符合以下签名:
        <修饰符>void <方法名>(IAsynResult asynResult);回调的方法的名称的统一规范是在名称前面加On ,如:OnAsynCallBack();(注:命名事件和委托等类型时候同样有类似的惯例),
        2.工作机制:
        .Net使用从线程池中得到的线程来执行通过BeginInvoke()分配的方法,当异步方法执行完成时,工作线程调用回调方法而不只直接回到线程池中,要实现回调方法,我们必须在使用beginInvoke()方法的时候指定一个参数为IAsynResult类型的方法,因为在AsynResult是一个.Net中已经定义好的委托,我们要使用回调方法的话,就必须符合他的要求:他的定义如下,public delegate void AsynCallBack(IAsynResult asynResult);

        示例:

        
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Messaging;
using System.Diagnostics;

namespace Asyn
{
    
public delegate int BinaryOperation(int argument1,int argument2);

    
class Program
    
{
        
static void Main(string[] args)
        
{
            CalCulatorClent.AsynAdd();
        }

    }


    
public class Calculator
    
{
        
public int Add(int argument1, int argument2)
        
{
            
return argument1 + argument2;
        }


        
public int Sub(int argument1, int argument2)
        
{
            
return argument1 - argument2;
        }

    
    }


    
public class CalCulatorClent
    
{
        
public static void AsynAdd()
        
{

            Calculator calculator 
= new Calculator();
            BinaryOperation oppDel 
= calculator.Add;
            oppDel.BeginInvoke(
23, OnMethodCompletion, null);

        }

        
private static void OnMethodCompletion(IAsyncResult asynResult)
        
{
            
int result = 0;

            AsyncResult resultObj
=(AsyncResult)asynResult;
            System.Diagnostics.Debug.Assert(resultObj.EndInvokeCalled
==false);//如果没调用,则输出

            BinaryOperation oppDel 
= (BinaryOperation)resultObj.AsyncDelegate;//获取原来的委托
            result = oppDel.EndInvoke(asynResult);
            Console.WriteLine(
"Operation returned "+result.ToString());
            Console.Read();
        }

    }


}

            
注:上面的示例有一个要值得注意,就是获取原始委托的方法,获取原始委托用的是System.Runtime.Remoting.Messaging;
名字空间下的AsynResult,它继承自IAsynResult,通过它的AsyncDelegate属性,我们就得到了对应BeginInvoke()方法的委托,同时还可以利用它的属性EndInvokeCalled来确定EndInvoke()是否被调用。

二:回调方法与线程安全
   因为回调方法是在线程池中的一个线程中运行的,所以关于线程安全方面也要考虑。特别是对于一些共享资源如数据库连接对象等就要考虑到并发带来的问题,我们可以加同步锁(用lock关键字)来访问这些资源。

三:传递状态信息

BeginInvoke()的最后一个参数,object asyncState,作为.NET中的作为泛用容器被提供的状态对象。处理方法完成的部分可以访问类似于IAsyncResult中AsyncState属性的容器对象。虽然也可以在其他.NET异步调用编程模型(阻塞,等待或轮询)中使用状态对象,但与完成方法一起使用时最有用处。原因很简单:在其他编程模型中,不仅必须管理IAsyncResult对象,而且还要管理一个额外的增加管理责任的容器对象。当通过完成回调使用容器对象时,仅需要给回调方法传入一个额外的参数,而且已通过.NET在方法签名中预订了。





转载于:https://www.cnblogs.com/hanchan/archive/2007/09/18/897094.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值