2014-05-16 16 views
6

Tôi muốn viết như sau:Nhiệm vụ giá trị trả về, mà không tác <T> (async/chờ đợi mẫu)

public string GetSomeValue() 
{ 
    //directly return the value of the Method 'DoSomeHeavyWork'... 
    var t = DoSomeHeavyWork(); 
    return t.Result; 
} 

public Task<string> DoSomeHeavyWork() 
{ 
    return Task.Run(() => { 
     // do some long working progress and return a string 
     return "Hello World!"; 
    }); 
} 

Như bạn có thể nhìn thấy trở lại kết quả từ DoSomeHeavyWork() Tôi đã sử dụng tài sản Task.Result , hoạt động tốt, nhưng theo các nghiên cứu, điều này sẽ chặn Chủ đề.

Tôi muốn sử dụng mẫu async/await cho điều này nhưng không thể dường như tìm cách thực hiện việc này. Nếu tôi đã làm như vậy với async/chờ đợi với kiến ​​thức hiện tại của tôi, tôi sẽ luôn luôn kết thúc với điều này:

public async Task<string> GetSomeValue() 
{ 
    //directly return the value of the Method 'DoSomeHeavyWork'... 
    var t = DoSomeHeavyWork(); 
    return await t; 
} 

public Task<string> DoSomeHeavyWork() 
{ 
    return Task.Run(() => { 
     // do some long working progress and return a string 
     return "Hello World!"; 
    }); 
} 

Giải pháp này doesnt khá phù hợp với nhu cầu của tôi bởi vì tôi muốn trở lại CHỈ chuỗi và không phải là một Task<string>, làm thế nào điều này có thể đạt được với async/await?

+0

Tại sao bạn không thể trở về 'Nhiệm vụ ' bởi vì khi bạn 'await' nó nó trả về một' chuỗi'. Đó không phải là những gì bạn muốn? – Enigmativity

Trả lời

10

Bạn không thể.

Toàn bộ điểm của async là để chạy mã không đồng bộ. Vì vậy, mã trả về một lời hứa của giá trị string tương lai, được trình bày trong .NET dưới dạng Task<string>.

Hãy suy nghĩ theo cách này: nếu mã của bạn gọi public string GetSomeValue(), thì vào thời điểm phương thức trả về, bạn đã có một string. Điều này là đồng bộ, theo định nghĩa.

Trong ví dụ của bạn, bạn có tác phẩm "nặng" mà tôi hiểu là "CPU bị ràng buộc". Trong trường hợp đó, chỉ cần thực hiện công việc đồng bộ:

public string DoSomeHeavyWork() 
{ 
    // do some long working progress and return a string 
    return "Hello World!"; 
} 

Nói chung, API không nên "nói dối"; nếu chúng đồng bộ, thì chúng phải có chữ ký đồng bộ (không phải là Task -quay lại).

Chỉnh sửa: Theo nhận xét của bạn, tác vụ "nặng" là cuộc gọi WCF, được I/O-ràng buộc, không bị ràng buộc CPU.

Trong trường hợp đó, tác phẩm tự nhiên không đồng bộ. Sử dụng phương pháp WCF không đồng bộ (không Task.Run), và cho phép sự không đồng bộ để phát triển thông qua codebase của bạn:

public async Task<string> GetSomeValueAsync() 
{ 
    //directly return the value of the Method 'DoSomeHeavyWork'... 
    var t = DoSomeHeavyWorkAsync(); 
    return await t; 
} 

public async Task<string> DoSomeHeavyWorkAsync() 
{ 
    // Call asynchronous WCF client. 
    await ...; 
    return "Hello World!"; 
} 
+0

Làm thế nào bạn sẽ giải quyết được vấn đề của tôi, với thuộc tính 'Task.Result' hoặc bạn có biết gì hơn không? (Sẽ rất vui về đoạn mã nếu bạn biết cách thay thế tốt hơn) –

+0

Trong ví dụ trực tiếp của tôi, tôi đang gọi một yêu cầu WCF cho một máy khách và muốn có một phương thức chạy async để không chặn máy khách trong khi máy chủ đang gọi phương thức (cả máy chủ/máy khách là WPF) tôi có nên trả lại đối tượng Task thay vì chuỗi/đối tượng được giải quyết không? –

+0

Tôi đã chỉnh sửa câu trả lời của mình bằng giải pháp ưa thích của mình: chỉ cần thực hiện công việc trực tiếp. Và tôi đã chỉnh sửa lại lần nữa vì tác phẩm "nặng" là yêu cầu WCF. –

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