繁体   English   中英

关于多线程的问题

[英]Questions about multi-threading

如果我有一个线程:

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();
        }

这取决于计时器的类型。 可以在后台线程中工作的大多数计时器(System.Timers.Timer或System.Threading.Timer)使用ThreadPool线程作为其Tick事件。 在这种情况下,答案是“两个”线程。

如果您的计时器是Windows窗体计时器或DispatcherTimer,它可能会导致异常,因为它们需要在UI线程上运行,并且不能在后台线程上运行。

这将取决于您正在使用的计时器。 .NET Framework有几个计时器;

  • System.Threading.Timer =可以在任何可用的线程上。
  • System.Windows.Forms.Timer =应该在“UI”线程上。
  • System.Timer.Timer =可以在任何可用的线程上。

可能还有更多我想念的东西。

如上所述,有两个计时器; System.Threading.Timer和System.Windows.Forms.Timer。 第一种可以在任何线程上执行,除了你从它开始的线程(除非它是线程池的一部分,你的函数已经返回,然后它可能会在那里执行,最终。)

第二种,Windows窗体类,可以在您的线程或另一个线程上执行。 这取决于。

计时器需要一个窗口句柄,并且根据创建句柄的线程,Tick事件将在不同的线程上触发。 计时器使用的内部窗口是在第一次需要时创建的。 最有可能的是,您已在主(GUI)线程上创建了计时器,但这不会在计时器内创建实际窗口。 要确保在主线程上创建窗口,您必须首先启动,然后至少停止计时器一次。 (这是第一次创建窗口时启动的。)

(如果你没有得到它:计时器使用内部窗口来接收tick事件。窗口是在一个线程上创建的,该线程需要运行消息循环。首先启动计时器的线程将创建窗口,并接收Tick事件。希望该线程正在运行一个messageloop。)

如果您希望每隔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,因此它已经在一次原子操作中进行检查和出列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM