我是C#线程的新手。 有没有为线程设置超时而不阻塞调用线程(在C#3.5中)?
如果没有,使用线程执行函数是否合乎逻辑,并且在该函数内创建一个线程并加入它来克服这个主线程阻塞问题?举例说明:
而不是:
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 :(得分:4)
我检查过,最简单,最全面的方法就是我在问题描述中提到的解决方案。中级线程可以轻松地等待第二个线程而不会中断主线程;如果它在所需的时间内没有响应,它可以杀死第二个线程。这正是我所需要的。我使用它并且它没有问题。
答案 1 :(得分: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);
}
}
}
答案 2 :(得分:1)
您可能还想看一下为您做很多事情的ThreadPool.QueueUserWorkItem()
(http://msdn.microsoft.com/en-us/library/kbf0f1ct.aspx)。
正如布莱恩评论的那样,中止线程通常不是一件明智的事情,因为在那一刻它可能正在做一些重要的事情。
答案 3 :(得分:0)
请参阅:http://www.techtalkz.com/c-c-sharp/111717-thread-timeout.html
查看TimeSpan方法http://msdn.microsoft.com/en-us/library/23f7b1ct.aspx
答案 4 :(得分: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.
}
}
答案 5 :(得分:0)
“加入成员 - &gt;阻止调用线程,直到线程终止,同时继续执行标准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);
}
}
答案 6 :(得分: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();
}
不确定未完成的线程会发生什么。
答案 7 :(得分:-1)
我创建了一个 C# 类来执行带有超时的线程,并且不会阻塞调用线程。
using System;
using System.Collections.Generic;
using System.Threading;
using System.Timers;
namespace some_name_space
{
class TimedThread
{
private Thread thread;
private static List<TimedThread> timedThreads = new List<TimedThread>();
private Int32 timeout = 5000;
private System.Timers.Timer timer;
public TimedThread(ThreadStart start) { thread = new Thread(start); }
public int Timeout { get => timeout; set => timeout = value; }
public System.Timers.Timer Timer { get => timer; }
public Thread _Thread { get => thread; }
public void run()
{
timer = new System.Timers.Timer(timeout);
timer.Elapsed += OnTimedEvent;
timer.AutoReset = false;
timer.Enabled = true;
_Thread.Start();
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
TimedThread tt = timedThreads.Find(t => t.timer.Equals(source));
if (tt != null)
tt.thread.Abort("Timeout exception");
}
}
}
使用这个类:
TimedThread tt = new TimedThread(SomeWorkToDo);
tt.Timeout = 5000;
tt.run();