2017-12-22 46 views
5

Tôi có một máy chủ web và có một công việc định kỳ sáp nhập và gửi các bản ghi (nhiều nhật ký yêu cầu).Chính xác thì điều gì sẽ xảy ra khi gọi phương thức async mà không phải chờ từ khóa?

Task.Run(() => 
{ 
    while (true) 
    { 
     try 
     { 
      MergeAndPutRecords(); 
     } 
     catch (Exception ex) 
     { 
      Logger.Error(ex); 
     } 
    } 
}); 

Trong chức năng MergeAndPutRecords, có các bản ghi hợp nhất mã và chức năng async trả về Bản ghi gửi tác vụ. (Actaully đó là Amazon Kinesis Firehose's PutRecordBatchAsync.)

Sau đó, điều gì sẽ xảy ra nếu tôi gọi chức năng đó mà không phải chờ từ khóa? Có chức năng chạy trên thread tách ra? Here says it is not. Sau đó, những gì đang trở về Task Means? Here nói phương pháp async mà không cần chờ đợi từ khóa có nghĩa

  1. Bắt đầu phương pháp đồng bộ trên thread hiện hành. Bỏ qua tất cả các kết quả (bao gồm cả ngoại lệ).

Sau đó, công việc định kỳ và PutRecordBatchAsync của tôi được xử lý đồng thời? Tôi biết asynchronouse và đồng thời là khác nhau. Nhưng không có từ khóa chờ đợi và chúng nằm trong cùng một chuỗi. Cái nào sẽ được thực hiện trước? Tôi đang bối rối ...

Sẽ có các bản ghi lớn cần được hợp nhất và gửi trong thời gian thực. Vì vậy, tôi nghĩ rằng nó phải được thực hiện đồng thời ..

+3

Từ khoá 'async' không tự làm bất kỳ điều gì. Mỗi 'await' được kết hợp thành một 'AsyncStateMachine' có thể xử lý các công cụ không đồng bộ. Nếu bạn không có từ khóa 'await' bên trong phương thức' async' thì không có lý do gì để tạo ra 'AsyncStateMachine', vì vậy bạn sẽ có được phương thức đồng bộ. – FCin

+3

'await' được sử dụng để * chờ kết quả đến *. Nó không, trong bất kỳ cách nào, kiểm soát * làm thế nào quá trình để có được kết quả là ** bắt đầu *** hoặc làm thế nào quá trình liên tục để có được kết quả là làm việc. –

Trả lời

5

Sau đó, công việc định kỳ và PutRecordBatchAsync của tôi được xử lý đồng thời?

Sử dụng API tác vụ, bạn có thể đảm bảo rằng chúng được thực thi đồng thời (sử dụng Hồ sơ chủ đề), nhưng bạn cần hiểu sự khác biệt giữa hoạt động đồng thời bộ nhớ Vs IO.

Trong khi đồng bộ bộ nhớ không có lợi khi sử dụng Tác vụ, cuộc gọi IO một lần được thực thi không cần chuỗi gì cả, vì nó dựa trên phần cứng đồng thời, nếu nó sử dụng chuỗi, tất cả những gì nó sẽ làm để quay trở lại, do đó lãng phí tài nguyên hệ thống quý giá và giảm khả năng mở rộng hệ thống

Trường hợp IO dựa trên đồng thời, như bạn gọi là API dựa trên mạng/từ xa

Đúng sự thật Hoạt động không đồng bộ sẽ giải phóng ngữ cảnh luồng, trên cửa sổ nó sẽ sử dụng cổng hoàn thành IO (cơ chế xếp hàng) để thực hiện cuộc gọi Async, trong khi chuỗi gọi được sử dụng để gửi các cuộc gọi tương tự khác, cần bối cảnh thread khi trả về cuộc gọi IO để phục vụ phản hồi và cho điều đó nữa, nếu không phải là cuộc gọi giao diện người dùng, sau đó sử dụng ConfigureAwait(false), để bất kỳ ngữ cảnh luồng nào có thể được sử dụng để gửi phản hồi.

Điều gì sẽ xảy ra nếu bạn không sử dụng với điều kiện không đồng bộ?

Cuộc gọi có nghĩa là Không đồng bộ trở thành Đồng bộ và ngay lập tức sẽ ảnh hưởng đến khả năng mở rộng hệ thống, vì các chủ đề hiện bị chặn, thậm chí tệ hơn cho một hoạt động IO chạy dài. Bạn đã từng thấy cách các khung công tác JavaScript luôn thực hiện cuộc gọi AJAX (Async) đến API máy chủ, do đó, có thể có nhiều công việc hơn nữa để ngăn chặn các luồng Trình duyệt.

Nói chung cho Trong bộ nhớ chế biến bạn sẽ tạo ra số lượng nhất định Nhiệm vụ và xử lý chúng bằng Task.WaitAll hoặc Parallel.ForEach cho một bộ sưu tập, để chế biến async, lý tưởng giới thiệu không phải là để có một Task.Run bất cứ nơi nào, nó thích phải Async từ điểm vào, giống như có thể trong trường hợp MVC, các bộ điều khiển có thể không đồng bộ. Nhiều cuộc gọi được nhóm lại với nhau bằng cách sử dụng Task.WhenAll Tác vụ đại diện và sau đó được chờ đợi. thậm chí nếu bạn sử dụng Task.Run như trong mã của bạn, sau đó sử dụng async lambda để thực hiện một cuộc gọi không đồng bộ

Tóm tắt:

của nó bắt buộc phải sử dụng await cho các cuộc gọi không đồng bộ, nếu không họ async từ khóa là vô ích trong bối cảnh đó và có await sẽ đợi cuộc gọi IO quay trở lại trước khi tiếp tục được thực hiện, mặc dù không có luồng nào bị chặn trong quá trình

0

Nếu phương thức trả về Task, cách tốt nhất là luôn quan sát kết quả của số Task tại một số điểm. Nó có thể là giá trị trả về được khai báo, hoặc nó có thể là một ngoại lệ. Nếu bạn muốn quan sát nhiệm vụ đó trước khi phương pháp của bạn tiếp tục, await là đề xuất.

Trong trường hợp này, có thể bạn nên quan sát kết quả của Task được trả lại bởi PutRecordBatchAsync. Bạn sẽ muốn biết nếu cuộc gọi không thành công vì bất kỳ lý do nào vì điều này có thể chỉ ra rằng các bản ghi của bạn không được lưu trữ!

Trong mã ví dụ bạn đã cung cấp, bạn sẽ thấy rằng bạn thực hiện các cuộc gọi tiếp theo đến MergeAndPutRecords trước khi cuộc gọi trước đó hoàn tất. Bạn có chắc chắn rằng điều này được dự định không?

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