C# 异步操作

3

实际上,我很难理解BeginInvoke()和EndInvoke()的配对。

class AsynchronousDemo
{

    public delegate void DemoDelegate();
    static void Main()
    {

        DemoDelegate d = PrintA;

        IAsyncResult AResult = d.BeginInvoke(Callback,null);
        d.EndInvoke(AResult);
        Console.ReadKey(true);
    }

    static void PrintA()
    {
        Console.WriteLine("....Method in Print A Running ....");
        Thread.Sleep(4000);
        Console.WriteLine("....Method in Print A Completed...");
    }


    static void Callback(IAsyncResult ar)
    {
        Console.WriteLine("I will be finished after method A 
        completes its execution");
    }
}

1) 我们是否使用 "EndInvoke()" 来指示 BeginInvoke() 的结束 "异步操作"?

2) 这对的真正用途是什么?

3) 我可以得到一些简单而好的例子来更好地理解它吗?

4个回答

11

想象一下,你有一个很长的任务要完成,每次只能做一件事。通常,在进行此任务时,您必须停止做其他所有事情。

// pseudocode
Main() {
    DoLaundry()
    GoAboutYourDay()
}

DoLaundry() {
    // boring parts here
}

现在想象一下,当你的衣服正在洗的时候,你希望能够继续去做其他事情。一个解决方案是找别人来洗。所以你把它拿到洗衣店,告诉他们该怎么做,交给他们你的衣服,并告诉他们在完成后给你打电话。作为回报,他们会给你一张票据,这样当你想要取回你的衣服时,他们就可以找到它。

// pseudocode
Main() {
   ticket = DoLaundry.BeginDoing(CallMeWhenDone)
   GoAboutYourDay()
   ticket.WaitUntilDone()
}

CallMeWhenDone(ticket) {
   cleanLaundry = DoLaundry.FinishDoing(ticket)
}

这就是异步操作的工作原理。

BeginInvoke:您告诉程序需要完成什么任务(委托),在完成时要调用哪个方法(回调函数)以及使用什么方式来完成任务(状态)。您会得到一个IAsyncResult对象,您需要将其返回以接收结果。然后,您可以执行其他操作,或使用IAsyncResult中的WaitHandle来阻塞直到操作完成。

Callback:当异步操作完成时,它将调用此方法,并给您相同的IAsyncResult。此时,您可以从其中检索出状态对象,或将IAsyncResult传递给EndInvoke。

EndInvoke:该函数接受IAsyncResult并查找操作的结果。如果尚未完成,则该函数将阻塞,直到完成,这就是为什么通常在回调内部调用它的原因。

这是一种经常在框架中使用的模式,不仅限于函数委托。类似于数据库连接、套接字等所有东西都经常具有Begin/End对。

MSDN上有关于该模式的文档:http://msdn.microsoft.com/en-us/library/2e08f6yc(VS.71).aspx


非常好的解释。对像我这样的初学者非常有用。 - user215675

1

我使用Begin Invoke / End Invoke结构来运行Windows服务。

例如:

    public ServiceName()
    {
        //constructor code goes here
    }

    protected override void OnStart(string[] args)
    {
        ExecuteDelegate ed = new ExecuteDelegate(Execute);
        AsyncCallback ac = new AsyncCallback(EndExecution);
        IAsyncResult ar = ed.BeginInvoke(ac, ed);
        Log.WriteEntry("Service has started.");
    }

    protected void EndExecution(IAsyncResult ar)
    {
        ExecuteDelegate ed = (ExecuteDelegate)ar.AsyncState;
        ed.EndInvoke(ar);
        Stop();
        Log.WriteEntry("Service has stopped.");
    }

    protected void Execute()
    {
       //Code goes here
       ...
    }

    protected override void OnStop()
    {
        Log.WriteEntry("Service has stopped.");
    }

本质上:调用BeginInvoke在新线程中启动方法的执行。当线程结束时,当线程加入时调用的方法应该调用EndInvoke。


1

BeginInvoke是启动异步操作,EndInvoke等待该函数的结束并返回结果。这是在C#中执行线程的另一种方式,其主要特点是begininvoke从线程池中获取线程,而对于Thread类来说则不正确,另一个特点是您可以更轻松地传递参数和获取线程函数的结果。以下是一个示例http://ondotnet.com/pub/a/dotnet/2003/02/24/asyncdelegates.html


1

我不知道如何充分解释,但这篇文章应该会有所帮助:
使用委托进行异步编程 在 MSDN 上

摘录:
.............如果调用了 BeginInvoke 方法,公共语言运行时 (CLR) 会将请求排队,并立即返回给调用者。目标方法在线程池中的线程上异步调用。提交请求的原始线程可以自由地继续并行执行目标方法。如果在调用 BeginInvoke 方法时指定了回调方法,则目标方法结束时会调用回调方法。在回调方法中,EndInvoke 方法获取返回值和任何输入/输出或仅输出参数。如果在调用 BeginInvoke 时未指定回调方法,则可以从调用 BeginInvoke 的线程中调用 EndInvoke.....

1)我们是否使用 "EndInvoke()" 来表示 BeginInvoke() 的结束 "异步操作"?
不,您使用它来获取返回值或...请参见上文

2) 这些对的真正用途是什么?
这样你就可以在同步方法上进行异步调用等操作。

3) 我能否得到一些简单而好理解的例子来更好地理解它?
我相信谷歌可以比我做得更好 :P


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接