2013-07-16 33 views
16

Tôi đang sử dụng thư viện cung cấp các phương thức kết thúc bằng ...Async và trả lại Task. Tôi sẽ sử dụng chúng trong ứng dụng dòng lệnh . Vì vậy, tôi cần phải gọi cho họ một cách đồng bộ rất nhiều.Đợi công việc không đồng bộ mà không bao gồm ngoại lệ trong AggregateException

C# tất nhiên không cho phép gọi các phương thức này theo phương thức Main vì bạn không thể sử dụng phương thức async trên phương thức Main. Giả sử đây là nhiệm vụ:

var task = datastore.Save(data); 

tôi tìm thấy một số giải pháp như:

Tasks.WaitAll(task); 
task.Wait(); 

tuy nhiên tất cả những trường hợp ngoại lệ bọc ném vào AggregateException, Tôi không muốn điều đó. Tôi chỉ muốn nói task.Result và tôi mong đợi ngoại lệ ban đầu sẽ được ném.

Khi tôi sử dụng phương thức trả lại Task<TResult>, task.Result ném AggregateException mặc dù không có nhiệm vụ tiếp tục được đặt. Tại sao sự rung động này?

Tôi cũng đã cố gắng,

task.RunSynchronously(); 

nó mang lại cho lỗi:

RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.

vì vậy tôi đoán đó là không cho các phương pháp đánh dấu là async.

Bất kỳ ý tưởng nào về mẫu sử dụng thư viện được thiết kế cho ứng dụng không đồng bộ trong ứng dụng bảng điều khiển không có ngữ cảnh không đồng bộ?

Trả lời

27

I am going to use these in a command line application. So I need to call them synchronously a lot.

Không, bạn không. Bạn có thể sử dụng async - await trong ứng dụng bảng điều khiển, bạn chỉ cần thực hiện một async để đồng bộ hóa quá trình chuyển đổi ở trên cùng. Và bạn có thể làm điều đó bằng cách sử dụng Wait():

public static void Main() 
{ 
    MainAsync().Wait(); 
} 

public static async Task MainAsync() 
{ 
    var datastore = …; 
    await datastore.SaveAsync(); 
} 

Thông thường, kết hợp với awaitWait() là một ý tưởng tồi (nó có thể gây bế tắc), nhưng đó là giải pháp ngay tại đây.

Lưu ý rằng nếu SaveAsync() ném ngoại lệ và bạn không nắm bắt được nó, nó sẽ được gọi lại là AggregateException từ Wait(). Nhưng bạn có thể coi đó là ngoại lệ ban đầu trong MainAsync() (vì nó không sử dụng Wait()).

Nếu bạn thực sự muốn nhận ngoại lệ đầu tiên được ném trực tiếp, bạn có thể làm điều gì đó tương tự như những gì await thực hiện: task.GetAwaiter().GetResult(). Lưu ý rằng nếu Task chứa nhiều hơn một ngoại lệ, bạn sẽ chỉ nhận được một ngoại lệ đầu tiên (nhưng cũng áp dụng cho trường hợp đầu tiên là await).

When I use a method returning Task<TResult> , task.Result throws AggregateException even though there are no continuation tasks set. Why is this happening?

Điều này không liên quan gì đến việc tiếp tục. Một đơn Task có thể đại diện cho nhiều thao tác và mỗi thao tác có thể ném một ngoại lệ. Do đó, các phương pháp Taskluôn luôn ném các ngoại lệ được bao bọc trong một số AggregateException.

I also have tried task.RunSynchronously()

Điều đó không có ý nghĩa gì. RunSynchronously() chỉ có thể được sử dụng trên Task s đã được tạo bằng cách sử dụng hàm tạo Task. Đó không phải là trường hợp ở đây, vì vậy bạn không thể sử dụng nó. Task s được trả về từ các phương thức không đồng bộ luôn được khởi động.

2

Bạn có thể tạo ra một hình nộm Main

public static void Main() 
{ 
    MainAsync().Wait(); 
} 

public static async Task MainAsync() 
{ 
    try { 
     var result = await dataStore.Save(data); 
    } catch(ExceptionYouWantToCatch e) { 
     // handle it 
    } 
} 

Ngoài ra, xem câu trả lời này: https://stackoverflow.com/a/9212343/1529246

Các vấn đề liên quan