【发布时间】:2014-12-25 08:17:06
【问题描述】:
在我的 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 创建了一个类似的演示。
【问题讨论】:
-
m_VoiceResponse.Stop() 永远不应执行,因为如果请求取消,您将在上一行抛出异常
-
@BobVale,请从 OneDrive 播放我的演示,您会发现问题所在。它只是使用了
Console.WriteLine()。(完全没有例外)。 -
cToken.ThrowIfCancellationRequested()将引发异常 -
@BobVale,我删除了那行但同样的事情。如果你想看看我在onedrive.live.com/… 上的干净源代码,你就会明白问题出在哪里了。
标签: c# task-parallel-library c#-5.0