簡體   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