2010-02-15 38 views
34

Tôi có đối tượng obj đó là thành phần bên thứ 3,Đặt thời gian chờ để phẫu thuật

// this could take more than 30 seconds 
int result = obj.PerformInitTransaction(); 

Tôi không biết những gì đang xảy ra bên trong. Điều tôi biết là nếu mất nhiều thời gian hơn thì không thành công.

cách thiết lập cơ chế thời gian chờ cho thao tác này, để mất hơn 30 giây tôi chỉ cần ném MoreThan30SecondsException?

Trả lời

66

Bạn có thể chạy các hoạt động trong một thread riêng biệt và sau đó đặt một thời gian chờ trên thread tham gia hoạt động:

using System.Threading; 

class Program { 
    static void DoSomething() { 
     try { 
      // your call here... 
      obj.PerformInitTransaction();   
     } catch (ThreadAbortException) { 
      // cleanup code, if needed... 
     } 
    } 

    public static void Main(params string[] args) { 

     Thread t = new Thread(DoSomething); 
     t.Start(); 
     if (!t.Join(TimeSpan.FromSeconds(30))) { 
      t.Abort(); 
      throw new Exception("More than 30 secs."); 
     } 
    } 
} 
+1

@Bomboca: Tôi cuộn lại chỉnh sửa của bạn, 'Exception' Tôi ném không phải là một' ThreadAbortException', mà là một cái gì đó ném bởi CLR khi có cuộc gọi để 'Hủy bỏ 'được thực hiện. –

+0

xin lỗi về điều đó và cảm ơn cho đầu vào :) –

+2

Đó là một cuộc gọi chặn, nếu bạn cần chủ đề chính làm những việc khác tại thời điểm này, điều này sẽ không hoạt động! – feldeOne

1

Bạn có thể nhìn vào cách gọi phương pháp này trong một chủ đề và khi thời gian chờ, hủy bỏ các chủ đề và tăng ngoại lệ. Ngoài ra, bạn sẽ phải xử lý các ngoại lệ ThreadBorted trong trường hợp này.

+0

Bạn đúng về ThreadAbortedException, +1. –

0

Có một ví dụ điển hình về giải pháp chung cho việc này bằng cách sử dụng lớp trợ giúp here.

Sử dụng đại biểu Hành động để tránh tạo/hủy luồng được hiển thị trong ví dụ trước.

Tôi hy vọng điều này sẽ hữu ích.

2

Bạn cần phải cẩn thận về việc hủy bỏ một thao tác như thế này, đặc biệt là khi nó nằm trong thành phần của bên thứ 3 mà bạn (có thể) không có quyền truy cập vào mã để sửa đổi.

Nếu bạn hủy bỏ thao tác thì bạn sẽ không biết trạng thái bạn đã để lại lớp cơ bản. Ví dụ: nó có thể đã có khóa và sự cố của bạn đã khiến khóa đó không được giải phóng. Ngay cả khi bạn phá hủy đối tượng sau khi hủy bỏ hoạt động, nó có thể đã thay đổi một số trạng thái toàn cục và nó sẽ không thể tạo ra một cá thể mới một cách đáng tin cậy mà không cần khởi động lại.

6

Nếu bạn không muốn chặn các chủ đề chính, bạn có thể sử dụng một System.Threading.Timer:

private Thread _thread; 

void Main(string[] args) 
{ 
    _thread = new ThreadStart(ThreadEntry); 
    _thread.Start(); 
    Timer timer = new Timer(Timeout,null,30000,Timeout.Infinite); 
} 


void ThreadEntry() 
{ 
    int result = obj.PerformInitTransaction(); 
} 

void TimeOut(object state) 
{ 
    // Abort the thread - see the comments 
    _thread.Abort(); 

    throw new ItTimedOutException(); 
} 

Jon Skeet có một cách ít mạnh mẽ (Shutting Down Worker Threads Gracefully) ngăn chặn các chủ đề hơn hủy bỏ.

Tuy nhiên, vì bạn không kiểm soát hoạt động PerformInitTransaction() đang làm ở đó, bạn không thể làm gì nhiều khi hủy bỏ và rời khỏi đối tượng ở trạng thái không hợp lệ. Như đã đề cập nếu bạn có thể xóa mọi thứ hủy bỏ PerformInitTransaction đã bị treo, bạn có thể thực hiện việc này bằng cách bắt số ThreadAbortException, mặc dù vì đó là cuộc gọi của bên thứ 3, điều đó có nghĩa là đoán trạng thái bạn đã để phương thức của mình.

PerformInitTransaction thực sự là thiết bị cung cấp thời gian chờ.

10

Nhiều chỉ đơn giản là sử dụng Task.Wait(TimeSpan):

using System.Threading.Tasks; 

var task = Task.Run(() => obj.PerformInitTransaction()); 
if (task.Wait(TimeSpan.FromSeconds(30))) 
    return task.Result; 
else 
    throw new Exception("Timed out"); 
+0

Điều này rất đơn giản và có sẵn kể từ .net 4.0. –

+0

Điều này sẽ không giết chết luồng mặc dù –

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