2013-07-19 128 views
0

我需要監視一個任務,並在需要的時間超過一個定義的超時時間後終止它。操作超時TPL

到目前爲止,我有很多嘗試都是從創建線程和發出線程中止等開始的。然後,我決定使用TPL。

您必須假定WorkItem是黑盒子。您無權訪問其源代碼。所以,重寫它讓它跟蹤令牌是不現實的。這需要從外面控制。

任何想法?

public class WorkItem : IDisposable 
    { 
    private System.Diagnostics.Stopwatch _watch = new System.Diagnostics.Stopwatch(); 
    private List<string> _messages = new List<string>(); 

    public void WriteMessage(string message) 
    { 
     _messages.Add(message); 
    } 

    public void Run() 
    { 
     for (int i = 1; i <= 25; i++) 
     { 
     System.Threading.Thread.Sleep(1000); 
     Console.WriteLine("Slept one second after {0} iteration.", i); 
     } 
    } 

    public void Dispose() 
    { 
     _watch.Stop(); 
     Console.WriteLine("Disposed... lived for {0} milliseconds", _watch.ElapsedMilliseconds); 
    } 
    } 

    class Program 
    { 
    static void Main(string[] args) 
    { 
     int timeout = 5000; 
     WorkItem item = new WorkItem(); 
     System.Threading.Tasks.Task task = System.Threading.Tasks.Task.Factory.StartNew<WorkItem>((arg) => 
     { 
     WorkItem currentWorkItem = arg as WorkItem; 
     currentWorkItem.Run(); 
     return currentWorkItem; 
     }, item); 

     bool wait = task.Wait(timeout); 
     if (wait == false) 
     { 
     Console.WriteLine("It took more than {0} ms.", timeout); 
     // Need a way to kill the task. 
     } 

     Console.WriteLine("Okay Waiting"); 
     Console.ReadKey(); 
    } 
    } 
+1

無論你做什麼 - 不要「中止」線程。通過搜索找到許多失敗的人。 – usr

+0

'WorkItem'是否有一個重載的[CancelationToken](http://msdn.microsoft.com/zh-cn/library/system.threading.cancellationtoken.aspx)?你說你不能重寫它來跟蹤一個標記,但你從來沒有說過它是否已經接受了一個標記。或者是否有其他內置的用於中斷'Run()'的接口? –

+0

號碼 這是一個黑匣子。 – Sam

回答

3

有一個原因,Task沒有辦法讓你取消它在外部。當你運行一個黑匣子時,不知道它在殺死它時會做什麼。它可能會持有鎖。它可能正在修改某些共享狀態。它可能會做任何事情,如果中斷,會使您的程序處於未知且非常可能的腐敗狀態。中止一個線程就像關閉電腦的電源開關一樣。不知道你會毀了什麼。

我非常強烈建議什麼,我要建議,但是如果你真的絕對必須在死亡的痛苦或失去你的工作搬起石頭砸自己的頭...... errrr,給你的程序殺的能力你的黑匣子,然後用線程做。

WorkItem threadResult = null; 
Thread t = new Thread((arg) => 
    WorkItem currentWorkItem = arg as WorkItem; 
    currentWorkItem.Run(); 
    threadResult = currentWorkItem; 
    }, item); 

// wait for thread to exit 
bool done = t.Join(timeout);    
if (!done) 
{ 
    t.Abort(); 
} 

再一次,我不承擔因使用此技術而可能導致的任何負面後果的責任。中止線程幾乎總是會讓你陷入困境。

+1

我真的猶豫了,但你把適當的免責聲明放在這個策略上。 – usr

+0

感謝您的發佈,我欣賞這個警告:-) 我這樣做,我認爲這是不對的。所以,我回到TPL之前就放棄了。但是,你的觀點是很好的! 謝謝 – Sam