如何停止游戏并在TPL中返回正确的价值观

本文关键字:返回 价值观 TPL 何停止 游戏 | 更新日期: 2023-09-27 18:28:13

在我的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(remainder, cToken);中停止进程并没有帮助,尽管我传入了取消令牌。

现在让我们来看看方法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上创建了一个类似的演示。

如何停止游戏并在TPL中返回正确的价值观

在检查令牌是否已取消并开始播放后,您将取消令牌。你再也回不去了,再也不会为了停止而执行那种状态。

你需要做的只是注册一个回调到代币的取消,停止玩家:

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

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

在微软MVP的帮助下,我终于找到了解决方案。Servy的解决方案很漂亮,但有缺陷。

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

注册应该放在开始播放之前,而不是之后。

编辑:2014年11月10日上午8:09

一个更好的:

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