使用TaskCompletionSource与队列和后台线程

时间:2016-11-25 21:52:31

标签: c# .net async-await

在我的ASP.NET API中,我收到了一系列要保留的消息。在这种特殊情况下,API的响应性取代了任何单个消息的重要性,因此我不是直接写入我的数据存储,而是将传入消息推送到队列并在后台线程上尽快处理它们。 / p>

在某些情况下,我可能需要确认写操作的成功或失败,因此我将消息包装在使用以下代码的自定义MessageContext对象中:

public class WriteMessageContext
{
    public Message Message { get; private set; }
    TaskCompletionSource<bool> complete = new TaskCompletionSource<bool>();

    public WriteMessageContext(Message message)
    {
        Message = message;
    }

    public Task<bool> WaitForInsert()
    {
        return complete.Task;
    }

    public void Success()
    {
        complete.SetResult(true);
    }

    public void Error()
    {
        complete.SetResult(false);
    }
}

Success和Error方法旨在由工作线程调用,该工作线程在后台处理每个排队的消息。然后,在我的控制器中,我可以这样做:

var ctx = new WriteMessageContext(msg);
queue.Enqueue(ctx);

// optionally...
if (await ctx.WaitForIt()) {
    // successful
} else {
    // or not
}

这是否恰当地使用了TaskCompletionSource + async / await,或者我是不是放弃了混蛋?是否有任何潜在的问题我应该这样做?

1 个答案:

答案 0 :(得分:1)

对我来说,这是.footer { position: absolute; bottom: 0; width: 100%; /* Set the fixed height of the footer here */ height: 60px; background-color: #f5f5f5; } 的有效用法。

顺便说一下,也许你会感到惊讶,因为任务并行库(TPL)中有一些名为data-flow blocks的隐藏功能/ gem。

实际上,有一个可以满足您的要求:BufferBlock<T>

  

TaskCompletionSource<T>类表示通用异步消息传递结构。此类存储可由多个源写入或由多个目标读取的消息的先进先出(FIFO)队列。当目标从BufferBlock<T>对象收到消息时,该消息将从消息队列中删除。因此,虽然BufferBlock<T>对象可以有多个目标,但只有一个目标将接收每个消息。当您想要将多个消息传递给另一个组件时,BufferBlock<T>类很有用,并且该组件必须接收每条消息。