Tôi đã sử dụng async (và .Net 4.5 thực sự) lần đầu tiên gần đây, và tôi đã bắt gặp một thứ khiến tôi bối rối. Không có nhiều thông tin về lớp VoidTaskResult mà tôi có thể tìm thấy trên Net nên tôi đến đây để xem có ai có ý tưởng gì về những gì đang xảy ra không.Loại VoidTaskResult là gì khi nó liên quan đến các phương thức không đồng bộ?
Mã của tôi giống như sau. Rõ ràng, điều này được đơn giản hóa nhiều. Ý tưởng cơ bản là gọi các phương thức plugin, không đồng bộ. Nếu họ trả về Tác vụ, thì không có giá trị trả về từ cuộc gọi không đồng bộ. Nếu họ trả lại tác vụ <>, thì có. Chúng ta không biết trước chúng thuộc loại nào, vì vậy ý tưởng là xem xét kiểu kết quả bằng cách sử dụng sự phản chiếu (IsGenericType là true nếu kiểu là Type <>) và nhận giá trị sử dụng kiểu động.
Trong mã thực của tôi, tôi đang gọi phương thức plugin thông qua phản ánh. Tôi không nghĩ điều này sẽ tạo nên sự khác biệt đối với hành vi mà tôi đang thấy.
// plugin method
public Task yada()
{
// stuff
}
public async void doYada()
{
Task task = yada();
await task;
if (task.GetType().IsGenericType)
{
dynamic dynTask = task;
object result = dynTask.Result;
// do something with result
}
}
Điều này phù hợp với phương pháp plugin được hiển thị ở trên. IsGenericType là sai (như mong đợi).
Tuy nhiên nếu bạn thay đổi khai báo của hàm Plugin bao giờ nên hơi, IsGenericType tại trả về true và các công cụ phá vỡ:
public async Task yada()
{
// stuff
}
Khi bạn làm điều này, các ngoại lệ sau đây được ném vào kết quả dòng (object = dynTask.Result;):
Nếu bạn thâm nhập vào các đối tượng nhiệm vụ, nó thực sự dường như là Type. VoidTaskResult là một kiểu riêng trong không gian tên Threading với hầu như không có gì trong đó.
tôi đã cố gắng thay đổi mã gọi tôi:
public async void doYada()
{
Task task = yada();
await task;
if (task.GetType().IsGenericType)
{
object result = task.GetType().GetProperty("Result").GetMethod.Invoke(task, new object[] { });
// do something with result
}
}
này "thành công" theo nghĩa là nó không còn ném, nhưng bây giờ kết quả là loại "VoidTaskResult" mà tôi có thể không hợp lý làm bất cứ điều gì với.
Tôi nên thêm rằng tôi đang gặp khó khăn trong việc xây dựng một câu hỏi thực sự cho tất cả điều này. Có lẽ câu hỏi thực sự của tôi là một cái gì đó giống như "VoidTaskResult là gì?", Hoặc "Tại sao điều kỳ lạ này lại xảy ra khi tôi gọi một phương thức động không đồng bộ?" hoặc thậm chí có thể "Làm cách nào để bạn gọi các phương thức plugin có tùy chọn không đồng bộ?" Trong mọi trường hợp, tôi đặt điều này ra ngoài với hy vọng rằng một trong những bậc thầy sẽ có thể làm sáng tỏ.
Tại sao nhóm async giới thiệu VoidTaskResult thay vì chỉ giới thiệu một TaskCompletionSource không chung chung? – Puppy
@Puppy: Tôi nghi ngờ vì nó hoạt động ít hơn rất nhiều. Viết một 'TaskCompletionSource' không nongeneric không quá khó, nhưng bất kỳ API công cộng nào cũng phải trải qua một loạt các" cổng "khác trước khi nó có thể được phát hành. Đánh giá bảo mật, v.v. –