简体   繁体   English

关于多线程的问题

[英]Questions about multi-threading

If I have a that thread: 如果我有一个线程:

Thread sendMessage = new Thread(new ThreadStart(timer.Start()));

will, the Tick event of the timer will be on the main thread or on the sendMessage thread? 将,计时器的Tick事件将在主线程或sendMessage线程上?

Edit: I have a queue and i want that every x milisecond the timer will tick and the program will dequeue arrays from the queue, but this is my code: 编辑:我有一个队列,我希望每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)
            {

            }

and I can't call a none static method or use a none static field from the checkIfQueue, and it have to be static, what can i do? 我不能调用非静态方法或使用checkIfQueue中的非静态字段,它必须是静态的,我该怎么办?

Edit: Here is the code that one of you sent me, I cahnged him so it fitts to my goal, will it work? 编辑:这是你们其中一个人发给我的代码,我给他打电话让它符合我的目标,它会起作用吗?

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

It depends on the type of timer. 这取决于计时器的类型。 Most timers (System.Timers.Timer or System.Threading.Timer) that can work in a background thread use a ThreadPool thread for their Tick event. 可以在后台线程中工作的大多数计时器(System.Timers.Timer或System.Threading.Timer)使用ThreadPool线程作为其Tick事件。 In this case, the answer is "neither" thread. 在这种情况下,答案是“两个”线程。

If your timer is a Windows Forms timer or a DispatcherTimer, it will likely cause an exception, since they need to be run on the UI thread, and can't be run on a background thread. 如果您的计时器是Windows窗体计时器或DispatcherTimer,它可能会导致异常,因为它们需要在UI线程上运行,并且不能在后台线程上运行。

This is going to depend on exactly which timer you are using. 这将取决于您正在使用的计时器。 The .NET Framework has several timers; .NET Framework有几个计时器;

  • System.Threading.Timer = Could be on any available thread. System.Threading.Timer =可以在任何可用的线程上。
  • System.Windows.Forms.Timer = Should be on the "UI" thread. System.Windows.Forms.Timer =应该在“UI”线程上。
  • System.Timer.Timer = Could be on any available thread. System.Timer.Timer =可以在任何可用的线程上。

And probably more that I'm missing. 可能还有更多我想念的东西。

As mentioned, there are two timers; 如上所述,有两个计时器; System.Threading.Timer and System.Windows.Forms.Timer. System.Threading.Timer和System.Windows.Forms.Timer。 The first kind may execute on any thread, except the thread you started it from (unless it's part of the threadpool, and your function has returned, then it might be executed there, eventually.) 第一种可以在任何线程上执行,除了你从它开始的线程(除非它是线程池的一部分,你的函数已经返回,然后它可能会在那里执行,最终。)

The second kind, the Windows Forms kind, may execute on either your thread, or another thread. 第二种,Windows窗体类,可以在您的线程或另一个线程上执行。 It depends. 这取决于。

The timer needs a window handle, and depending on which thread the handle is created, the Tick event will fire on different threads. 计时器需要一个窗口句柄,并且根据创建句柄的线程,Tick事件将在不同的线程上触发。 The internal window the timer uses is created when it's needed for the first time. 计时器使用的内部窗口是在第一次需要时创建的。 Most likely, you have created the timer on the main (GUI) thread, but that will not create the actual window inside the timer. 最有可能的是,您已在主(GUI)线程上创建了计时器,但这不会在计时器内创建实际窗口。 To ensure that the window is created on the main thread you will have to first start, and then stop, the timer at least one time. 要确保在主线程上创建窗口,您必须首先启动,然后至少停止计时器一次。 (It's when started for the first time the window is created.) (这是第一次创建窗口时启动的。)

(If you didn't get it: the timer uses an internal window to receive the tick event. The window is created on a thread, and that thread needs to have message loop running. The thread that is first to start the timer will create the window, and receive the Tick event. Hopefully that thread is running a messageloop.) (如果你没有得到它:计时器使用内部窗口来接收tick事件。窗口是在一个线程上创建的,该线程需要运行消息循环。首先启动计时器的线程将创建窗口,并接收Tick事件。希望该线程正在运行一个messageloop。)

If you are wanting to dequeue items from a queue every X milliseconds then why use a timer at all? 如果您希望每隔X毫秒从队列中出列项目,那么为什么要使用计时器呢? It is much easier to spawn a new thread that spins around an infinite loop. 生成一个围绕无限循环旋转的新线程要容易得多。

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

Update: 更新:

No, your method is not thread-safe. 不,您的方法不是线程安全的。 The problem is with how you are dequeueing items. 问题在于你如何出列物品。

if (messageQueue.Count > 0)
{
  messageQueue.TryDequeue(out array);
}

It should really look like this. 它应该看起来像这样。

if (messageQueue.TryDequeue(out array)
{
}

The TryDequeue method returns false if the queue is empty so it already does the check and dequeue in one atomic operation. 如果队列为空,则TryDequeue方法返回false,因此它已经在一次原子操作中进行检查和出列。

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

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