2012-11-22 71 views
24

thể trùng lặp:
Set timeout to an operationLàm thế nào để thiết lập thời gian chờ cho một dòng C# mã

Làm thế nào tôi có thể thiết lập thời gian chờ cho một dòng mã trong C#. Ví dụ: RunThisLine(SomeMethod(Some Input), TimeSpan.FromSeconds(10)) chạy SomeMethod với thời gian chờ 10 giây. Cảm ơn trước.

+1

Đó là "dòng" của hợp tác mã, tức là bằng cách nào đó có hỗ trợ hủy không? –

+0

Không, quá trình xử lý dòng phải được giới hạn trong thời gian quy định. – Hossein

Trả lời

71

Bạn có thể sử dụng Task Parallel Library. Để chính xác hơn, bạn có thể sử dụng Task.Wait(TimeSpan):

using System.Threading.Tasks; 

var task = Task.Run(() => SomeMethod(input)); 
if (task.Wait(TimeSpan.FromSeconds(10))) 
    return task.Result; 
else 
    throw new Exception("Timed out"); 
+3

Thật tuyệt vời. Kết quả của 'SomeMethod' sẽ nằm trong biến' task.Result'. Cảm ơn. – Hossein

+6

Không cần sử dụng 'CancellationToken' nếu bạn chỉ cần thời gian chờ, và/hoặc phương pháp của bạn không xử lý mã thông báo khi hủy. Chờ đợi có quá tải mà không có 'mã thông báo' hoạt động tốt. – trapicki

+0

Hãy cẩn thận guys, _might_ này thay đổi hành vi của ứng dụng (như trong trường hợp của tôi) – copa017

5

tôi sử dụng một cái gì đó như thế này (bạn nên thêm mã để đối phó với nhiều thất bại):

var response = RunTaskWithTimeout<ReturnType>(
     (Func<ReturnType>)delegate { return SomeMethod(someInput); }, 30); 


    /// <summary> 
    /// Generic method to run a task on a background thread with a specific timeout, if the task fails, 
    /// notifies a user 
    /// </summary> 
    /// <typeparam name="T">Return type of function</typeparam> 
    /// <param name="TaskAction">Function delegate for task to perform</param> 
    /// <param name="TimeoutSeconds">Time to allow before task times out</param> 
    /// <returns></returns> 
    private T RunTaskWithTimeout<T>(Func<T> TaskAction, int TimeoutSeconds) 
    { 
     Task<T> backgroundTask; 

     try 
     { 
      backgroundTask = Task.Factory.StartNew(TaskAction); 
      backgroundTask.Wait(new TimeSpan(0, 0, TimeoutSeconds)); 
     } 
     catch (AggregateException ex) 
     { 
      // task failed 
      var failMessage = ex.Flatten().InnerException.Message); 
      return default(T); 
     } 
     catch (Exception ex) 
     { 
      // task failed 
      var failMessage = ex.Message; 
      return default(T); 
     } 

     if (!backgroundTask.IsCompleted) 
     { 
      // task timed out 
      return default(T); 
     } 

     // task succeeded 
     return backgroundTask.Result; 
    } 
+2

Xin lưu ý: Thao tác này không hủy hành động sau thời gian chờ. Tôi không nói rằng nó nên làm điều đó - Tôi đang đề cập đến nó bởi vì tôi nghĩ rằng đây là một chi tiết quan trọng. –

9

Bạn có thể sử dụng IAsyncResult và hành động lớp/giao diện để đạt được điều này.

public void TimeoutExample() 
    { 
     IAsyncResult result; 
     Action action =() => 
     { 
      // Your code here 
     }; 

     result = action.BeginInvoke(null, null); 

     if (result.AsyncWaitHandle.WaitOne(10000)) 
      Console.WriteLine("Method successful."); 
     else 
      Console.WriteLine("Method timed out."); 
    } 
+2

Rất đơn giản để sử dụng !! Nhưng làm điều này cũng giết nhiệm vụ khác hay? (trong trường hợp hết thời gian chờ) –

+0

nhiệm vụ khác = hành động * –

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