1

我正在创建一个windows phone 8.1应用程序。当应用程序启动时,应用程序会提示用户拨打特定的电话号码。它用声音做到这一点。通过应用程序告知说明后,显示电话呼叫对话框。 这是代码:如何避免异步方法windows phone 8.1

public MainPage() 
    { 
     this.InitializeComponent(); 

     this.NavigationCacheMode = NavigationCacheMode.Required; 
     StartSpeaking("Please call number !"); 

     CallDialog(); 
    } 

    private async void StartSpeaking(string text) 
    { 

     MediaElement mediaElement = this.media; 

     // The object for controlling the speech synthesis engine (voice). 
     var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer(); 

     // Generate the audio stream from plain text. 
     SpeechSynthesisStream stream = await synth.SynthesizeTextToStreamAsync(text); 

     // Send the stream to the media object. 
     mediaElement.SetSource(stream, stream.ContentType); 
     mediaElement.Play(); 



    } 

private async void CallDialog() 
    { 

     Windows.ApplicationModel.Calls.PhoneCallManager.ShowPhoneCallUI("123", "123"); 
     var messageDialog = new Windows.UI.Popups.MessageDialog("call ended", "Text spoken"); 
     await messageDialog.ShowAsync(); 
    } 

的问题是,我必须用synth.SynthesizeTextToStreamAsync方法是异步方法这么叫的对话框显示出来,据说文本之前。我怎样才能避免这种情况?

回答

2

async Task方法应该被接受;它只是应该避免的async void方法(它们只能用作事件处理程序)。我有一个MSDN article that describes a few reasons to avoid async void

在你的情况,你可以使用一个async void事件处理程序(例如,用于Loaded事件),让你的方法async Task代替async voidawait他们:

async void MainPage_Loaded(..) 
{ 
    await StartSpeakingAsync("Please call number !"); 
    await CallDialogAsync(); 
} 

private async Task StartSpeakingAsync(string text); 
private async Task CallDialogAsync(); 

更新

要(异步)等待媒体播放,您需要挂钩一个事件,通知您它已完成。 MediaEnded看起来是个不错的选择。像这样的东西应该工作:

public static Task PlayToEndAsync(this MediaElement @this) 
{ 
    var tcs = new TaskCompletionSource<object>(); 
    RoutedEventHandler subscription = null; 
    subscription = (_, __) => 
    { 
    @this.MediaEnded -= subscription; 
    tcs.TrySetResult(null); 
    }; 
    @this.MediaEnded += subscription; 
    @this.Play(); 
    return tcs.Task; 
} 

这种方法扩展了MediaElementasync -ready PlayToEndAsync方法,您可以使用这样的:

private async Task SpeakAsync(string text) 
{ 
    MediaElement mediaElement = this.media; 
    var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer(); 
    SpeechSynthesisStream stream = await synth.SynthesizeTextToStreamAsync(text); 
    mediaElement.SetSource(stream, stream.ContentType); 
    await mediaElement.PlayToEndAsync(); 
} 
+0

是的,我明白这一点,但即使我去这样,当应用程序启动时,我仍然可以调用对话框,而不是在请求之前拨打号码。 – n32303 2014-09-06 17:56:32