2010-07-07 57 views
8

我是新来的线程在C#中。 有没有为线程设置超时而不阻塞调用线程(在C#3.5中)?c中的线程超时#

如果不是,使用线程执行函数并在该函数中创建线程并加入它以克服此主线程阻塞问题是否合乎逻辑?为了说明:

相反的:

Public void main() 
{ 
     ... 
     Thread thrd1 = new Thread(new ThreadStart(targetObj.targetFunc)); 
     thrd1.Start(); 
     thrd1.Join(); 
     ... 
} 

使用类似:

Public void main() 
{ 
     ... 
     Thread thrd1 = new Thread(new ThreadStart(middleObj.waiter)); 
     thrd1.Start(); 
     ... 
} 

//And in the middleObj.waiter(): 
Public void waiter() 
{ 
     Thread thrd2 = new Thread(new ThreadStart(targetObj.targetFunc)); 
     thrd2.Start(); 
     thrd2.Join(); 
} 
+0

相似http://stackoverflow.com/questions/299198/implement-c-sharp-generic-timeout – Kiquenet 2013-04-12 09:20:37

回答

4

我检查过,最简单和最全面的方法是我在问题描述中提到的解决方案。中级线程可以轻松等待第二个线程,而不会中断主线程;如果它在所需的时间内没有响应,它可以杀死第二个线程。这正是我需要的。我用它,它工作没有问题。

+0

我只是添加这个答案,以防有人碰到同样的问题,并希望看到我到底在哪里。谢谢大家的帮助。 – DeveloperInToronto 2011-03-15 16:01:12

0

最简单的事情请致电Thread.Join在你的主线程的安全点,并传递你想等待连接发生的时间。

public static void Main() 
{ 
    TimeSpan timeout = TimeSpan.FromSeconds(30); 
    Thread thread = new Thread(() => { ThreadMethod(); }); 
    thread.Start(); 
    DateTime timeStarted = DateTime.UtcNow; 
    DoSomeWorkOnThisThread(); 
    // We are at a safe point now so check the thread status. 
    TimeSpan span = DateTime.UtcNow - timeStarted; // How long has the thread been running. 
    TimeSpan wait = timeout - span; // How much more time should we wait. 
    if (!thread.Join(wait)) 
    { 
    thread.Abort(); // This is an unsafe operation so use as a last resort. 
    } 
} 
+0

避免Thread.Abort总是一个好主意。 在你没有创建的线程上避免它会更好。 如何停止.NET中的线程(以及为什么Thread.Abort是邪恶的) http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation Thread.Abort的危险Eric Lippert http://blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx – Kiquenet 2013-04-15 08:08:13

+0

@Kiquenet他已经提到“这是一个不安全的操作所以用作最后的手段。“为线程中止。相反,信号可以用来安全地返回阻塞线程。 – 2014-09-24 13:30:28

1

你可能也想看看ThreadPool.QueueUserWorkItem()http://msdn.microsoft.com/en-us/library/kbf0f1ct.aspx),它做了很多的东西给你。

正如Brian所评论的,放弃一个线程通常不是一件聪明的事情,因为它可能正在做一些重要的事情。

0

“加入成员 - >阻止调用线程,直到线程终止,同时继续执行标准COM和SendMessage抽取。” MSDN网站。

thrd1.Join()告诉调用线程等到thrd1完成。

我最喜欢的解决方案是做一个小班,我可以控制线程的执行。

public class MyClass 
    { 
     private bool _stop; 
     private Thread _myThread; 

     public void Stop() 
     { 
      _stop = true; 
      //Will block the calling thread until the thread die 
      _myThread.Join(); 
     } 

     public void Run() 
     { 
      _stop = false; 
      _myThread = new Thread(Work); 
     } 

     public void Work() 
     { 
      do 
      { 

      } while (!_stop); 
     } 
    } 
0

使用middleObject方案查看WaitHandle.WaitOne()方法。

Public void main() 
{ 
    ... 
    middleObj.WaitHandle.Reset(); 
    Thread thrd1 = new Thread(new ThreadStart(middleObj.waiter)); 
    thrd1.Start(); 
    middleObj.WaitHandle.WaitOne(timeout); 
    ... 
} 


//And in the middleObj.waiter(): 
Public void waiter() 
{ 
    Thread thrd2 = new Thread(new ThreadStart(targetObj.targetFunc)); 
    thrd2.Start(); 
    thrd2.Join(); 
    this.WaitHandle.Set(); 
} 

不知道未完成的线程会发生什么情况。

2

您可以为每个线程启动一个System.Threading.Timer并将它传递给线程的ManagedThreadId。保持活动线程及其定时器的字典,由ManagedThreadId键入。如果计时器到期,请使用传递的线程ID来中止线程并终止计时器。如果线程正常完成,调用一个回调来杀死定时器。这里有一个简单的控制台例子:

using System; 
using System.Collections.Generic; 
using System.Threading; 

namespace ConsoleApplication2 
{ 
    public delegate void KillTimerDelegate(int arg); 

    class Program 
    { 
     static Dictionary<int, Thread> activeThreads = new Dictionary<int, Thread>(); 
     static Dictionary<int, Timer> activeTimers = new Dictionary<int, Timer>(); 
     static void Main(string[] args) 
     { 
      for (int i = 0; i < 10; i++) 
      { 
       Worker worker = new Worker(); 
       worker.DoneCallback = new KillTimerDelegate(KillTimer); 
       Thread thread = new Thread(worker.DoWork); 
       activeThreads.Add(thread.ManagedThreadId, thread); 
       thread.IsBackground = true; 

       thread.Start(); 
       Timer timer = new Timer(TimerCallback, thread.ManagedThreadId, 500, 500); 
       activeTimers.Add(thread.ManagedThreadId, timer); 
      } 
      Console.ReadKey(); 
     } 

     static void TimerCallback(object threadIdArg) 
     { 
      int threadId = (int)threadIdArg; 
      if (activeThreads.ContainsKey(threadId)) 
      { 
       Console.WriteLine("Thread id " + threadId.ToString() + " aborted"); 
       activeThreads[threadId].Abort(); 
       KillTimer(threadId); 
      } 
     } 

     static void KillTimer(int threadIdArg) 
     { 
      activeThreads.Remove(threadIdArg); 
      activeTimers[threadIdArg].Dispose(); 
      activeTimers.Remove(threadIdArg); 
     } 
    } 

    public class Worker 
    { 
     public KillTimerDelegate DoneCallback { get; set; } 
     Random rnd = new Random(); 

     public void DoWork() 
     { 
      Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " started"); 
      Thread.Sleep(rnd.Next(0, 1000)); 
      Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString() + " finished normally"); 
      DoneCallback(Thread.CurrentThread.ManagedThreadId); 
     } 
    } 
} 
+0

避免Thread.Abort总是一个好主意。 在你没有创建的线程上避免它会更好。 如何停止.NET中的线程(以及为什么Thread.Abort是邪恶的) http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation Thread.Abort的危险由Eric Lippert http://blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx – Kiquenet 2013-04-15 07:55:33