在AsyncCallback中使用操作

时间:2015-11-17 09:46:04

标签: c# asynchronous delegates asynccallback

我的课程做了以下(简化):

public void Startup(Action myAction)
{
    _myAction = myAction;
}

private void EstablishApplicationEndpoint()
{
    ...
    ApplicationEndpoint.BeginEstablish(OnApplicationEndpointEstablishCompleted, null);
}

private void OnApplicationEndpointEstablishCompleted(IAsyncResult result)
{
    try
    {
        ...
        _myAction();
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception);
    }
}

BeginEstablish方法将AsyncCallback作为第一个参数。

但是永远不会执行myAction(我使用控制台应用程序中的类)。该操作应输出一些内容到控制台并读取一行,但控制台立即关闭。

我的控制台应用程序:

static void Main(string[] args)
{
    StartPlatform();
}

private static void StartPlatform()
{
    ...
    _platformController.Startup(SendContext);
}

private static void SendContext()
{
    Console.WriteLine("Press ENTER to send context");
    Console.ReadLine();
    ...
}

由于控制台无法知道ReadLine - 呼叫将在某个时间到来,它会自动关闭。我怎么能阻止这样做?

1 个答案:

答案 0 :(得分:2)

您正在使用'异步编程模型(APM)模式: https://msdn.microsoft.com/en-us/library/ms228963(v=vs.110).aspx

此模型的典型代表是使用BeginEnd方法。

请注意,当调用Begin方法(例如您的BeginEstablish)时,回调方法表示的工作计划在单独的(后台)线程上进行,并返回程序控制立即在主线程中。

假设是其他计算可以在主线程上发生,在某些时候回调将在后台线程上完成,然后后台线程的结果将重新连接到主线程。

重新加入的机制是调用相应的End方法(因此在您的情况下,调用EndEstablish)。因此,为了防止您的控制台应用程序因呼叫从BeginEstablish立即恢复而退出,您需要执行以下操作:

  • 维护对IAsyncResult调用返回的Begin对象的引用
  • 在调用Begin之后的代码路径中的某个位置,调用相应的End,将通过调用获得的IAsyncResult对象传递给Begin
  • (可选)将第二个参数用于Begin调用以管理状态

这看起来像是:

private IAsyncResult EstablishApplicationEndpoint()
{
    ...
    return ApplicationEndpoint.BeginEstablish(OnApplicationEndpointEstablishCompleted, null);
}

...

private static void StartPlatform()
{
    ...
    _platformController.Startup(SendContext);
    var asyncResult = _platformController.EstablishApplicationEndpoint();

    // Do other things

    // Re-join the callback
    ApplicationEndpoint.EndEstablish(asyncResult);
}

请记住,如果在调用End时尚未完成回调,则End将在此时阻止并等待回调完成。

由于您的回调与控制台互动,我怀疑这意味着您的End电话会被阻止。