简体   繁体   English

当我的任务从自定义TaskScheduler启动时,'await'不会返回

[英]'await' does not return, when my Task is started from a custom TaskScheduler

Background: 背景:

I have a "Messenger" class. 我有一个“信使”课。 It sends messages. 它发送消息。 But due to limitations, let's say it can only send - at most - 5 messages at a time. 但是由于限制,我们说它一次只能发送 - 最多 - 5条消息。

I have a WPF application which queues messages as needed, and waits for the queued message to be handled before continuing. 我有一个WPF应用程序,它根据需要对消息进行排队,并在继续之前等待处理排队的消息。 Due to the asynchronous nature of the application, any number of messages could be await ed at any given time. 由于应用程序的异步性质,可以在任何给定时间await编辑任何数量的消息。

Current Implementation: 目前的实施:

To accomplish this, I've implemented a Task<Result> SendMessage(Message message) API within my messaging class. 为此,我在我的消息类中实现了一个Task<Result> SendMessage(Message message) API。 Internal to the messaging class is a custom TaskScheduler (the LimitedConcurrencyTaskScheduler from MSDN ), with its concurrency level set to 5. In this way, I would expect that no matter how many messages are queued, only 5 will be sent out at a time, and my client application will patiently wait until its respective message has been handled. 消息传递类的内部是一个自定义的TaskScheduler( 来自MSDNLimitedConcurrencyTaskScheduler ),其并发级别设置为5.这样,我希望无论排队多少消息,一次只发送5个消息,我的客户端应用程序将耐心等待,直到其相应的消息已被处理。

Problem: 问题:

When I await the SendMessage method, I can see via the debugger that the message was completed and the result returned, but my code never executes beyond the await ed method call! 当我await SendMessage方法时,我可以通过调试器看到消息已完成并返回结果,但我的代码永远不会执行await ed方法调用!

Is there some special considerations that need to be made, when await ing a Task which was scheduled using a different TaskScheduler? await使用其他TaskScheduler计划的任务时,是否需要进行一些特殊考虑?

Snipped Code: 剪切代码:

From my client/consuming function: 从我的客户/消费功能:

public async Task Frobulate()
{
    Message myMessage = new Message(x, y, z);
    await messenger.SendMessage(myMessage);

    //Code down here never executes!
}

From my messenger class: 从我的使者班:

private TaskScheduler _messengerTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(5);
private TaskFactory _messengerTaskFactory = new TaskFactory(_messengerScheduler);

public Task<Result> SendMessage(Message message)
{
    //My debugger has verified that "InternalSendMessage" has completed, 
    //but the caller's continuation appears to never execute
    return _messengerTaskFactory.StartNew(() => InternalSendMessage(message));
}

Update: 更新:

The 'freeze' does not actually appear to be caused by my custom TaskScheduler ; “冻结”实际上并不是由我的自定义TaskScheduler引起的; when I queue up the Task with the default TaskFactory , the same behavior occurs! 当我使用默认的TaskFactory排队Task时,会发生相同的行为! There must be something else happening at a more fundamental level, likely due to my own stupidity. 必须在更基础的层面上发生其他事情,可能是由于我自己的愚蠢。

Based on the comments, you probably have a deadlock because you're blocking on async code. 基于这些注释,您可能会遇到死锁,因为您正在阻止异步代码。

When using async, whenever there are thread restrictions on the SynchronizationContext or TaskScheduler and the code blocks using Task.Result or Task.Wait there's a possibility of deadlocking. 使用异步时,只要SynchronizationContextTaskScheduler上有线程限制,并且使用Task.ResultTask.Wait的代码块,就有可能出现死锁。 The asynchronous operation needs a thread to finish execution, which it can't get because the SynchronizationContext (or TaskScheduler in your case) is waiting for that same exact operation to complete before allowing "new" ones to run. 异步操作需要一个线程来完成执行,它无法获取,因为SynchronizationContext (或者你的情况下是TaskScheduler )在允许“new”运行之前等待完成相同的精确操作。

Go deeper in Stephen Cleary's blog post: Don't Block on Async Code 深入了解Stephen Cleary的博客文章: 不要阻止异步代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM