Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步方法中的意外行为_C#_Asp.net Mvc_Asynchronous - Fatal编程技术网

C# 异步方法中的意外行为

C# 异步方法中的意外行为,c#,asp.net-mvc,asynchronous,C#,Asp.net Mvc,Asynchronous,我正在尝试使用的aync方法当前遇到一些意外/不想要的行为。异步方法是RecognizeAsync。我无法等待这个方法,因为它返回void。发生的情况是,ProcessAudio方法将首先被调用,并且似乎会一直运行到完成,但是网页不会返回我的“联系人”视图,否则会出错。在方法运行完成后,我的处理程序中的断点开始被命中。如果我让它一直播放到完成,就永远不会发生重定向-在chrome调试器的网络选项卡中,“状态”将保持标记为挂起并挂起。我相信我的问题是由异步性问题引起的,但我无法确定它到底是什么 感

我正在尝试使用的aync方法当前遇到一些意外/不想要的行为。异步方法是
RecognizeAsync
。我无法等待这个方法,因为它返回void。发生的情况是,
ProcessAudio
方法将首先被调用,并且似乎会一直运行到完成,但是网页不会返回我的“联系人”视图,否则会出错。在方法运行完成后,我的处理程序中的断点开始被命中。如果我让它一直播放到完成,就永远不会发生重定向-在chrome调试器的网络选项卡中,“状态”将保持标记为挂起并挂起。我相信我的问题是由异步性问题引起的,但我无法确定它到底是什么

感谢所有的帮助

[HttpPost]
public async Task<ActionResult> ProcessAudio()
{
    SpeechRecognitionEngine speechEngine = new SpeechRecognitionEngine();
    speechEngine.SetInputToWaveFile(Server.MapPath("~/Content/AudioAssets/speechSample.wav"));
    var grammar = new DictationGrammar();
    speechEngine.LoadGrammar(grammar);

    speechEngine.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(SpeechRecognizedHandler);
    speechEngine.SpeechHypothesized += new EventHandler<SpeechHypothesizedEventArgs>(SpeechHypothesizedHandler);

    speechEngine.RecognizeAsync(RecognizeMode.Multiple);

    return View("Contact", vm); //first breakpoint hit occurs on this line
                                  //but it doesnt seem to be executed? 
}

private void SpeechRecognizedHandler(object sender, EventArgs e)
{
    //do some work
    //3rd breakpoint is hit here
}

private void SpeechHypothesizedHandler(object sender, EventArgs e)
{
    //do some different work
    //2nd breakpoint is hit here
}
[HttpPost]
公共异步任务ProcessAudio()
{
SpeechRecognitionEngine speechEngine=新建SpeechRecognitionEngine();
SetInputToWaveFile(Server.MapPath(“~/Content/AudioAssets/speechSample.wav”);
var grammar=新的听写语法();
加载语法(语法);
speechEngine.SpeechRecognized+=新事件处理程序(SpeechRecognizedHandler);
speechEngine.SpeechAspectioned+=新事件处理程序(SpeechAspectionedHandler);
speechEngine.RecognizeAsync(RecognizeMode.Multiple);
return View(“Contact”,vm);//第一个断点命中发生在这一行上
//但它似乎没有被执行?
}
私有void SpeechRecognizedHandler(对象发送方,事件参数e)
{
//做些工作
//第三个断点在这里被击中
}
私有void SpeechAspectionedHandler(对象发送方,事件参数e)
{
//做一些不同的工作
//第二个断点在这里被击中
}
更新:根据建议,我已将代码更改为(在ProcessAudio中):

使用(speechEngine)
{
SetInputToWaveFile(Server.MapPath(“~/Content/AudioAssets/speechSample.wav”);
var grammar=新的听写语法();
加载语法(语法);
speechEngine.SpeechRecognized+=新事件处理程序(SpeechRecognizedHandler);
speechEngine.SpeechAspectioned+=新事件处理程序(SpeechAspectionedHandler);
var tcsRecognized=new TaskCompletionSource();
speechEngine.RecognizeCompleted+=(发送方,eventArgs)=>tcsegnized.SetResult(eventArgs);
speechEngine.RecognizeAsync(RecognizeMode.Multiple);
尝试
{
var eventArgsRecognized=wait tcsRecognized.Task;
}
捕获(例外e)
{
投掷(e);
}
}
这导致了一些错误的行为:
返回视图(“Contact”,vm)
断点现在将在处理程序完成激发后命中,但是仍然没有发生重定向。我从未被引导到我的联系页面。我只是像以前一样无限期地浏览我的原始页面。

你做得太早了。当您点击返回视图时,语音引擎可能还没有启动

您需要等待,直到语音引擎触发最后一个事件。最好的方法是将基于事件的异步转换为

这可以通过使用

让我们来处理(我认为)应该是在
speechEngine之后触发的最后一个事件。调用RecognizeAsync
,即
SpeechRecognized
。我假设这是在语音引擎计算最终结果时触发的事件

因此,首先:

var tcs = new TaskCompletionSource<EventArgs>();
(…等等…如果没有识别语音会发生什么?我们还需要连接
SpeechRecognitionRejected
事件,并为这种类型的事件定义一个自定义异常子类…这里我将其称为
RecognitionFailedException
。现在我们捕获了识别过程的所有可能结果,因此我们希望
TaskCompletionSource
将在所有结果中完成。)

然后

现在,我们可以
等待
我们的
TaskCompletionSource
Task
属性:

try
{
    var eventArgs = await tcs.Task;
}
catch(RecognitionFailedException ex)
{
    //this would signal that nothing was recognized
}
对作为任务结果的EventArgs执行一些处理,并将可行的结果返回给客户端

在此过程中,您将创建需要正确处理的
IDisposable
实例

因此:


如果有人好奇,我通过以下方式解决了我的问题:

我改为使用
Recognize().为了克服这个问题,我将操作包装在一个线程中,并在运行线程后直接将其连接回主线程。代码如下:

using (speechEngine)
      {
        var t = new Thread(() =>
        {
          speechEngine.SetInputToWaveFile(@"C:\AudioAssets\speechSample.wav");
          speechEngine.LoadGrammar(dictationGrammar);

          speechEngine.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(SpeechRecognizedHandler);
          speechEngine.SpeechHypothesized += new EventHandler<SpeechHypothesizedEventArgs>(SpeechHypothesizedHandler);
          speechEngine.Recognize();
        });
        t.Start();
        t.Join();

      }
 }
使用(speechEngine)
{
var t=新线程(()=>
{
SetInputToWaveFile(@“C:\AudioAssets\speechSample.wav”);
加载语法(听写语法);
speechEngine.SpeechRecognized+=新事件处理程序(SpeechRecognizedHandler);
speechEngine.SpeechAspectioned+=新事件处理程序(SpeechAspectionedHandler);
speechEngine.Recognize();
});
t、 Start();
t、 Join();
}
}

我已经更新了我的答案,以反映您建议的更改。请查看我在这方面遇到的问题。这就是您想要的实现吗?@peggy我假设这是因为有不止一个
SpeechAspectived
事件。您能放弃处理
SpeechAspectived
事件的尝试,直接处理它吗h我的回答中概述的事件(即,代表最终结果的事件,而不是某种中间结果)如果这让你有所收获,我们可以找出如何处理
SpeechSuggestived
事件。我再次更新了我当前的尝试。现在,在尝试返回视图之前启动处理程序(我所有的模型和虚拟机看起来都很完美
speechEngine.SpeechRecognitionRejected += (sender, eventArgs) => 
                            tcs.SetException(new RecognitionFailedException());
speechEngine.RecognizeAsync(RecognizeMode.Multiple);
try
{
    var eventArgs = await tcs.Task;
}
catch(RecognitionFailedException ex)
{
    //this would signal that nothing was recognized
}
using(SpeechRecognitionEngine speechEngine = new SpeechRecognitionEngine())
{
    //use the speechEngine with TaskCompletionSource
    //wait until it's finished
    try
    {
        var eventArgs = await tcs.Task;
    }
    catch(RecognitionFailedException ex)
    {
        //this would signal that nothing was recognized
    }

} //dispose
using (speechEngine)
      {
        var t = new Thread(() =>
        {
          speechEngine.SetInputToWaveFile(@"C:\AudioAssets\speechSample.wav");
          speechEngine.LoadGrammar(dictationGrammar);

          speechEngine.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(SpeechRecognizedHandler);
          speechEngine.SpeechHypothesized += new EventHandler<SpeechHypothesizedEventArgs>(SpeechHypothesizedHandler);
          speechEngine.Recognize();
        });
        t.Start();
        t.Join();

      }
 }