如果我有一个线程:
Thread sendMessage = new Thread(new ThreadStart(timer.Start()));
会不会,计时器的Tick事件会在主线程上还是在sendMessage线程上?
修改 我有一个队列,我希望每x毫秒计时器都会打勾,程序会从队列中出列数组,但这是我的代码:
Thread sendMessage = new Thread(new ThreadStart(startThreadTimer));
public Queue<Array> messageQueue = new Queue<Array>();
System.Threading.Timer timer;
private void startThreadTimer()
{
System.Threading.TimerCallback cb = new System.Threading.TimerCallback(checkIfQueue);
timer = new System.Threading.Timer(cb, null, 4000, 30);
}
private static void checkIfQueue(object obj)
{
}
我无法调用非静态方法或使用checkIfQueue中的非静态字段,它必须是静态的,我该怎么办?
修改 这是你们其中一个人发给我的代码,我认为他符合我的目标,是否有效?
public ConcurrentQueue<Array> messageQueue = new ConcurrentQueue<Array>();
public void Example()
{
var thread = new Thread(
() =>
{
while (true)
{
Array array;
byte[] byteArray = {};
if (messageQueue.Count > 0)
{
messageQueue.TryDequeue(out array);
foreach (byte result in array)
{
byteArray[byteArray.Length] = result;
}
controllernp.Write(byteArray, 0, 100);
}
Thread.Sleep(30);
}
});
thread.IsBackground = true;
thread.Start();
}
答案 0 :(得分:5)
这取决于计时器的类型。可以在后台线程中工作的大多数计时器(System.Timers.Timer或System.Threading.Timer)使用ThreadPool线程作为其Tick事件。在这种情况下,答案是“两个”线程。
如果您的计时器是Windows窗体计时器或DispatcherTimer,它可能会导致异常,因为它们需要在UI线程上运行,并且不能在后台线程上运行。
答案 1 :(得分:3)
这取决于你正在使用哪个计时器。 .NET Framework有几个计时器;
可能还有更多,我错过了。
答案 2 :(得分:2)
如前所述,有两个计时器; System.Threading.Timer和System.Windows.Forms.Timer。第一种可以在任何线程上执行,除了你从它开始的线程(除非它是线程池的一部分,你的函数已经返回,然后它最终会在那里执行。)
第二种,Windows窗体类,可以在您的线程或另一个线程上执行。这取决于。
计时器需要一个窗口句柄,并且根据创建句柄的线程,Tick事件将在不同的线程上触发。计时器使用的内部窗口是在第一次需要时创建的。最有可能的是,您已在主(GUI)线程上创建了计时器,但这不会在计时器内创建实际窗口。要确保在主线程上创建窗口,您必须首先启动,然后至少停止计时器一次。 (它是在第一次创建窗口时启动的。)
(如果你没有得到它:计时器使用一个内部窗口来接收tick事件。窗口是在一个线程上创建的,该线程需要运行消息循环。首先启动的线程timer将创建窗口,并接收Tick事件。希望该线程正在运行一个消息循环。)
答案 3 :(得分:1)
如果您希望每隔X毫秒从队列中出列项目,那么为什么要使用计时器呢?产生一个围绕无限循环旋转的新线程要容易得多。
public class Example
{
private ConcurrentQueue<Array> m_Queue = new ConcurrentQueue<Array>();
public Example(int intervalMilliseconds)
{
var thread = new Thread(
() =>
{
while (true)
{
Array array;
while (m_Queue.TryDequeue(out array))
{
// Process the array here.
}
Thread.Sleep(intervalMilliseconds);
}
});
thread.IsBackground = true;
thread.Start();
}
public void Enqueue(Array array)
{
m_Queue.Enqueue(array);
}
}
<强>更新强>
不,您的方法不是线程安全的。问题在于你如何出列物品。
if (messageQueue.Count > 0)
{
messageQueue.TryDequeue(out array);
}
它应该看起来像这样。
if (messageQueue.TryDequeue(out array)
{
}
如果队列为空,则TryDequeue
方法返回false,因此它已经在一次原子操作中进行检查并出列。