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