2012-03-08 34 views
5

Tôi có một ứng dụng nhỏ cần kiểm tra chuỗi kết nối SQL cho một số kết nối (mỗi lần thực hiện một lần tại một thời điểm). Để làm điều này, tôi tạm thời đặt ConnectionTimeout = 5 để tránh phải đợi lâu nếu kết nối không hợp lệ và ConnectionTimeout = 0 (chờ mãi).TPL Cách thực hiện 'Gọi lại'

Để tránh treo UI trong khi chúng tôi cố gắng để Open() một kết nối xấu (thậm chí với ConnectionTimeout = 5 sự chờ đợi cho SqlException có thể lên đến hai mươi giây), tôi muốn chạy thử nghiệm trên một sợi riêng biệt sử dụng tác vụ song song Library (TPL). Vì vậy, tôi spin-off chủ đề mới của tôi như:

Task<bool> asyncTestConn = Task.Factory.StartNew<bool> 
    (() => TestConnection(conn, bShowErrMsg)); 
return asyncTestConn.Result; 

Vấn đề là điều này vẫn khóa UI (rõ ràng), vì nó đang chờ đợi kết quả trước khi trở về người gọi. Làm cách nào để cho phép mã trả lại quyền kiểm soát cho giao diện người dùng (giải phóng GUI) trong khi nhận kết quả cuối cùng từ không đồng bộ Task?

Ngoài ra, từ trong một Task tôi có thể hợp pháp làm MessageBox.Show("Some message") không? Điều này không hoạt động đối với BackgroundWorkers và chuỗi được gộp chung này là một chuỗi nền theo mặc định; nhưng nó không có vẻ là một vấn đề. Cảm ơn vì đã dành thời gian cho tôi.

Trả lời

4

Bạn là đúng, đây là nơi mà sự chờ đợi xảy ra:

return asyncTestConn.Result; 

Bạn chỉ có thể xây dựng các mã kết thúc-up ở đuôi của TestConnection() hoặc sử dụng một Tiếp tục:

// untested 
//Task<bool> asyncTestConn = Task.Factory.Create<bool> (
Task<bool> asyncTestConn = new Task<bool> (
    () => TestConnection(conn, bShowErrMsg)); 
asyncTestConn.ContinueWith(MyFinishCode); 
asyncTestConn.Start() 

Tôi có thể hợp pháp thực hiện MessageBox.Show("Some message") không?

Thực tế là, Hộp thư an toàn chỉ. Nên có thể từ một Bgw là tốt.

Nhưng bạn đang kéo dài tuổi thọ của Tác vụ lên rất nhiều, đó không phải là ý hay.

+0

Cảm ơn rất nhiều vì phản hồi của bạn. Toàn bộ ý tưởng là để lấy lại để vượt qua kiểm soát trở lại giao diện người dùng/GUI càng sớm càng tốt, làm thế nào để/có thể ở trên đạt được điều đó? Nếu tôi gọi đoạn mã trên từ một phương thức được gọi là 'ParrTestConn (SqlConnection conn, string bShowErrMsg)' thì tôi không thể nói 'asyncTestConn.ContinueWith (ParrTestConn (conn, bShowErrMsg))' ... Hoặc tôi có thể? – MoonKnight

+0

@Killer Bạn chỉ có thể quay lại sau khi bắt đầu(). GUI sẽ luôn đáp ứng khi sử dụng. –

+0

Tôi không có phương thức 'Task.Factory.Create ' avilible? – MoonKnight

5

Đối với TPL, ContinueWith là chính xác những gì bạn muốn. Mở rộng câu trả lời của Henk:

var asyncTestConn = Task.Factory.StartNew(() => TestConnection(conn, bShowErrMsg)); 
// Henk's "MyFinishCode" takes a parameter representing the completed 
// or faulted connection-testing task. 
// Anything that depended on your "return asyncTestConn.Result;" statement 
// needs to move into the callback method. 
asyncTestConn.ContinueWith(task => 
    { 
     switch (task.Status) 
     { 
      // Handle any exceptions to prevent UnobservedTaskException. 
      case TaskStatus.Faulted: /* Error-handling logic */ break; 
      case TaskStatus.RanToCompletion: /* Use task.Result here */ break; 
     } 
    }, 
    // Using this TaskScheduler schedules the callback to run on the UI thread. 
    TaskScheduler.FromCurrentSynchronizationContext()); 
+0

Thực sự hữu ích. Cảm ơn. Sự kết hợp của hai câu trả lời là hoàn toàn bạc hà. – MoonKnight

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