c# - 如何在 TPL 中停止播放并返回正确的值?

标签 c# task-parallel-library c#-5.0

在我的 TPL 应用程序中,我想通过方法 PlayTTS(string text) 播放文本到语音。

public static CancellationTokenSource cTokenSource = new CancellationTokenSource();
public static CancellationToken cToken = cTokenSource.Token;

然后在消费者方法中。

async Task Consumer()
    {
        try
        {
            var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = 50,
                CancellationToken = cToken
            };
            var consumerBlock = new ActionBlock<AppointmentReminder>(
            remainder =>
            {
               if (cToken.IsCancellationRequested)
                  return;
                Dictionary<string, string> dict = new OutboundDial(ts).RunScript(remainder, cToken);
                // update UI by the returned dictionary
            },
            executionDataflowBlockOptions);

            m_bufferBlock.LinkTo(
            consumerBlock, new DataflowLinkOptions { PropagateCompletion = true });
            await consumerBlock.Completion;
        }

我有一个按钮事件来取消进程(WPF)。

private void Cancel_Click(object sender, RoutedEventArgs e)
{
    cTokenSource.Cancel();
}

您看到 ActionBlock 中有 cToken.IsCancellationRequested,但是它并没有帮助停止方法 OutboundDial(ts).RunScript(剩余部分,cToken); 虽然我传入了取消 token 。

现在让我们看看RunScript方法。

public Dictionary<string, string> RunScript(AppointmentReminder callData, CancellationToken cToken)
    {
        try
        {
             m_ChannelResource = m_TelephonyServer.GetChannel() as SipChannel;
             m_VoiceResource = m_ChannelResource.VoiceResource;
             // Many logging
             // Dial out

            MakeTest(callData, cToken);
        }
        catch
         {throw;}
        finally
        {
            // destroy m_ChannelResource and m_VoiceResource
         }
        return dict;
    }

关键点是方法MakeTest,里面有PlayTTS

public void MakeTest(AppointmentReminder callData, CancellationToken cToken)
{
    try
    {
        if (!cToken.IsCancellationRequested)
        {
            m_VoiceResource.PlayTTS(callData.Text);  
        }
        else
        {
            cToken.ThrowIfCancellationRequested();
            m_VoiceResource.Stop(); // Stops any current activity on m_VoiceResource.
            dict["ConnectedTime"] = " no connection";
            dict["DialingResult"] = " cancellation";
        }

当我单击取消按钮时,我当前的代码未到达 m_VoiceResource.Stop() 部分。 所以我的问题是当cTokenSource.Cancel();时,如何让代码运行在:

m_VoiceResource.Stop(); // Stops any current activity on m_VoiceResource.
dict["ConnectedTime"] = " no connection";
dict["DialingResult"] = " cancellation";

编辑:2014 年 10 月 31 日下午 1:10

根据Servy的评论,我使用了cToken.Register(() => m_VoiceResource.Stop());

我在 OneDrive 创建了一个类似的演示。

最佳答案

在检查 token 是否已取消并开始播放后,您将取消 token 。你永远不会回去并再次执行该条件来停止。

您需要做的只是注册一个回调来取消 token 以停止玩家:

cToken.Register(() => m_VoiceResource.Stop());

只需在开始玩游戏后立即添加该注册即可。

关于c# - 如何在 TPL 中停止播放并返回正确的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26633533/

相关文章:

c# - 错误 CS1056 : Unexpected character '$' running the msbuild on a tfs continuous integration process

c# - 在 .net 4 上使用异步等待

c# - WPF中Form对应的 "this"是什么?

c# - 如何验证此 ADFS token ?

c# - 说明 async/await 和 Reactive (Rx) 扩展范例之间区别的代码示例?

c# - Pallellelized DFS : Would task explosion break this program for large graphs?

exception - async void、await 和异常 - 为什么 GUI 线程在 'await' 之后抛出的异常需要 AsyncVoidMethodBuilder 进行编码(marshal)?

c# - CLR 中的确定性 GC?

c# - 如何使用方法替换特定的字符串?

c# - Parallel.ForEach仅在未运行代码时才在启动时执行两次吗?