2011-06-08 148 views
8

我正在使用異步CTP編寫IO沉重的控制檯應用程序。但我遇到異常問題。使用void處理異步異常

public static void Main() 
{ 
    while (true) { 
    try{ 
     myobj.DoSomething(null); 
    } 
    catch(Exception){} 
    Console.Write("done"); 
    //... 
    } 
} 

//... 
public async void DoSomething(string p) 
{ 
    if (p==null) throw new InvalidOperationException(); 
    else await SomeAsyncMethod(); 
} 

並執行以下操作:「完成」被寫入到控制檯,然後我得到的調試異常,然後我按繼續我的程序中存在
什麼給?

回答

9

當您致電DoSomething()它基本上創建一個Task在引擎蓋下,並開始Task。由於您有void簽名,因此沒有Task對象發回信號或您可能已被阻止,因此執行直接完成。與此同時,任務會拋出一個無人問津的異常,我懷疑這就是程序終止的原因。

我想你想的行爲更像是這樣的:

public static void Main() 
{ 
    while (true) { 
    var t = myobj.DoSomething(null); 
    t.Wait(); 
    if(t.HasException) { 
     break; 
    } 
    } 
    Console.Write("done"); 
    //... 
    } 
} 

//... 
public async Task DoSomething(string p) 
{ 
    if (p==null) throw new InvalidOperationException(); 
    else await SomeAsyncMethod(); 
} 

這將在每個DoSomething阻塞,直到它完成,並退出循環,如果DoSomething扔。當然,那麼你真的沒有做任何異步。但是從僞代碼,我不能完全知道你想異步發生什麼。

主要外購:對異步方法使用void意味着您無法獲得異常,除非您使用異步方法。作爲一個同步調用,它基本上只是安排工作,結果消失在以太網中。

+0

我不能調用t.Wait(),因爲它阻塞了主控制檯線程,所以我不能輸入任何東西,所以SomeAsyncMethod永遠不會完成(對於我的用法見:http://stackoverflow.com/questions/6145246/how-to-write-c-5-async) – TDaver 2011-06-08 20:14:54

+0

但我想通了!我不會等待任務,將它們放入列表中,並且在每次IO操作(當它們可以拋出異常時)之後,我檢查列表是否有任何任務出錯! – TDaver 2011-06-08 20:56:58

+1

是的,通常最好啓動所有的任務,將它們收集到一個列表中,然後將其收集到一個TaskEx.WhenAll(listOfTasks).Wait()當你想收集所有的工作 – 2011-06-08 23:48:54

11

如果你給你的控制檯應用程序異步兼容的情況下(例如,AsyncContextdocssource)從我AsyncEx庫),那麼你就可以趕上傳播完成了這方面的異常,甚至從async void方法:

public static void Main() 
{ 
    try 
    { 
    AsyncContext.Run(() => myobj.DoSomething(null)); 
    } 
    catch (Exception ex) 
    { 
    Console.Error.WriteLine(ex.Message); 
    } 
    Console.Write("done"); 
} 

public async void DoSomething(string p) 
{ 
    if (p==null) throw new InvalidOperationException(); 
    else await SomeAsyncMethod(); 
} 
+4

你已經恢復了原力平衡。謝謝! – 2014-04-23 17:36:32