我有一个方法HandleAcceptedConnection,它位于Task.Run()下,我想异步运行(在另一个单独的线程中)。我尝试将HandleAcceptedConnection声明为async方法并且不调用await但它似乎不是异步运行。我可以确认我可以在另一个Task.Run()下拥有Task.Run()(通过观察线程ID),但这是推荐的吗?
private async void Start_Click(object sender, RoutedEventArgs e)
{
var task = Task.Run(() =>
{
while (isContinue)
{
var handler = listener.Accept();
// handle connection
Log("Before");
Log("ThreadId Accept " + Thread.CurrentThread.ManagedThreadId);
// i want to run method below asynchronously. i want to
// wrap it under Task.Run() but i am already under
// Task.Run(). i set HandleAcceptedConnection as async. i thought by not
// calling await on HandleAcceptedConnection, HandleAcceptedConnection
// is asynchronous
HandleAcceptedConnection(handler);
Log("After");
isContinue = true;
}
});
await task;
}
private async Task HandleAcceptedConnection(Socket handler)
{
Log("ThreadId HandleAcceptedConnection " + Thread.CurrentThread.ManagedThreadId);
Log("Under HandleAcceptedConnection");
Thread.Sleep(10000);
}
当我运行时,日志说
Before
Under HandleAcceptedConnection
After
我想要
Before
After
Under HandleAcceptedConnection
我希望HandleAcceptedConnection以异步方式运行。我应该将它包装在另一个Task.Run下还是已经异步?
答案 0 :(得分:2)
你试过吗
private async Task HandleAcceptedConnection(Socket handler)
{
Thread.Sleep(1000);
Log("Under HandleAcceptedConnection");
}
因为在另一个线程上做某事并不意味着它会被延迟。
答案 1 :(得分:1)
您应该使用AcceptTcpClientAsync
,那么您将不需要额外的线程。请查看this answer以获取示例。当有可用的自然异步版本时,请不要使用同步API。
已更新以解决评论。没有什么可以阻止您在Task.Run
内使用Task.Run
,您的代码可能看起来像这样(未经测试):
private async void Start_Click(object sender, RoutedEventArgs e)
{
var connectionTasks = new List<Task>();
Func<Task> handleConnection = async () =>
{
var connectionTask = Task.Run(() => HandleAcceptedConnection(handler));
connectionTasks.Add(connectionTask);
await connectionTask;
connectionTasks.Remove(connectionTask);
};
var task = Task.Run(() =>
{
while (isContinue)
{
var handler = listener.Accept();
// handle connection
Log("Before");
Log("ThreadId Accept " + Thread.CurrentThread.ManagedThreadId);
var connectionTask = handleConnection();
Log("After");
isContinue = true;
}
});
await task;
}