在 AsyncCallback 中使用操作
Use actions inside AsyncCallback
我的 class 执行以下操作(简化):
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
永远不会执行(我使用来自控制台应用程序的 class)。该操作应该向控制台输出一些内容并读取一行,但控制台立即关闭。
我的控制台应用程序:
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
- 调用会在某个时间自动关闭。我怎样才能防止这样做?
您正在使用 'Asynchronous Programming Model (APM)' 模式:
https://msdn.microsoft.com/en-us/library/ms228963(v=vs.110).aspx
此模型以使用 Begin
和 End
方法为代表。
请注意,当调用 Begin
方法(例如您的 BeginEstablish
)时,回调方法表示的工作将安排在单独的(后台)线程上进行,并且程序控制在主线程中 returned 立即。
假设其他计算可以在主线程上进行,在某个时候回调将在后台线程上完成,然后后台线程的结果将重新加入主线程。
重新加入的机制是调用相应的 End
方法(因此在您的情况下,调用 EndEstablish
)。因此,为了防止您的控制台应用程序由于调用 BeginEstablish
的直接 return 控制而退出,您需要执行以下操作:
- 维护对从
Begin
调用 中 return 编辑的 IAsyncResult
对象的引用
- 在调用
Begin
之后的代码路径中的某个点,调用相应的 End
,传入从调用 Begin
获得的 IAsyncResult
对象
- 可选地使用第二个参数到
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
的调用将在您的情况下被阻塞。
我的 class 执行以下操作(简化):
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
永远不会执行(我使用来自控制台应用程序的 class)。该操作应该向控制台输出一些内容并读取一行,但控制台立即关闭。
我的控制台应用程序:
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
- 调用会在某个时间自动关闭。我怎样才能防止这样做?
您正在使用 'Asynchronous Programming Model (APM)' 模式: https://msdn.microsoft.com/en-us/library/ms228963(v=vs.110).aspx
此模型以使用 Begin
和 End
方法为代表。
请注意,当调用 Begin
方法(例如您的 BeginEstablish
)时,回调方法表示的工作将安排在单独的(后台)线程上进行,并且程序控制在主线程中 returned 立即。
假设其他计算可以在主线程上进行,在某个时候回调将在后台线程上完成,然后后台线程的结果将重新加入主线程。
重新加入的机制是调用相应的 End
方法(因此在您的情况下,调用 EndEstablish
)。因此,为了防止您的控制台应用程序由于调用 BeginEstablish
的直接 return 控制而退出,您需要执行以下操作:
- 维护对从
Begin
调用 中 return 编辑的 - 在调用
Begin
之后的代码路径中的某个点,调用相应的End
,传入从调用Begin
获得的IAsyncResult
对象 - 可选地使用第二个参数到
Begin
调用来管理状态
IAsyncResult
对象的引用
这可能是这样的:
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
的调用将在您的情况下被阻塞。