简体   繁体   English

将数据传递到正在运行的线程的正确方法是什么

[英]What is the correct way to pass data to a running thread

In most cases when you create your thread you can prepare the data beforehand and pass it into the constructor or method. 在大多数情况下,创建线程时,可以预先准备数据并将其传递到构造函数或方法中。

However in cases like an open socket connection you will typically already have a thread created but wish to tell it to perform some action. 但是,在打开套接字连接的情况下,通常已经创建了一个线程,但希望告诉它执行某些操作。

Basic idea: 基本思路:

C#

private Thread _MyThread = new Thread(MyMethod);
this._MyThread.Start(param);   

Java

private Thread _MyThread = new Thread(new MyRunnableClass(param));
this._MyThread.start();

Now what?

So what is the correct way to pass data to a running thread in C# and Java? 那么,将数据传递给C#和Java中正在运行的线程的正确方法是什么?

Java Java的

You could basically have a LinkedList (a LIFO ) and proceed (with something) like this (untested) : 您基本上可以拥有一个LinkedListLIFO )并进行如下操作(未经测试):

 class MyRunnable<T> implements Runnable {
     private LinkedList<T> queue;
     private boolean stopped;
     public MyRunnable(LinkedList<T> queue) { 
         this.queue = queue; 
         this.stopped = false; 
     }
     public void stopRunning() {
         stopped = true;
         synchronized (queue) {
             queue.notifyAll();
         }
     }
     public void run() {
         T current;
         while (!stopped) {
             synchronized (queue) {
                 queue.wait();
             }
             if (queue.isEmpty()) {
                 try { Thread.sleep(1); } catch (InterruptedException e) {}
             } else {
                 current = queue.removeFirst();

                 // do something with the data from the queue

             }
             Thread.yield();
         }
     }
 }

As you keep a reference to the instance of the LinkedList given in argument, somewhere else, all you have to do is : 当您保留对参数中给出的LinkedList实例的引用时,在其他位置,您要做的就是:

 synchronized (queue) {
    queue.addLast(T);  // add your T element here. You could even handle some
                       // sort of priority queue by adding at a given index
    queue.notifyAll();
 }

One way to pass data to a running thread is by implementing Message Queues . 将数据传递给正在运行的线程的一种方法是实现Message Queues The thread that wants to tell the listening thread to do something would add an item to the queue of the listening thread. 想要告诉侦听线程做某事的线程会将一个项目添加到侦听线程的队列中。 The listening thread reads from this thread in a blocking fashion. 侦听线程以阻塞方式从该线程读取。 Causing it to wait when there are no actions to perform. 没有任何动作可等待。 Whenever another thread puts a message in the queue it will fetch the message, depending on the item and it's content you can then do something with it. 每当另一个线程将消息放入队列时,它都会提取该消息,具体取决于项目及其内容,然后您可以对其进行处理。

This is some Java / pseudo code: 这是一些Java /伪代码:

class Listener
{
   private Queue queue;
   public SendMessage(Message m)
   {
     // This will be executed in the calling thread.
     // The locking will be done either in this function or in the Add below
     // depending on your Queue implementation.
     synchronize(this.queue) 
     {
        this.queue.put(m);
     }
   }

   public Loop()
   {
     // This function should be called from the Listener thread.
     while(true) 
     {
        Message m = this.queue.take();
        doAction(m);
     }
   }

   public doAction(Message m)
   {
      if (m is StopMessage)
      {
        ...
      }
   }
}

And the caller: 和呼叫者:

class Caller
{
  private Listener listener;

  LetItStop()
  {
     listener.SendMessage(new StopMessage());
  }
}

Of course, there are a lot of best practices when programming paralllel/concurrent code. 当然,在编写并行/并发代码时,有很多最佳实践。 For example, instead of while(true) you should at the least add a field like run :: Bool that you can set to false when you receive a StopMessage. 例如,除了while(true)您至少应添加一个run :: Bool之类的字段,在收到StopMessage时可以将其设置为false。 Depending on the language in which you want to implement this you will have other primitives and behaviour to deal with. 根据您要实现该语言的语言,您将需要处理其他原语和行为。

In Java for example you might want to use the java.util.Concurrent package to keep things simple for you. 例如,在Java中,您可能想使用java.util.Concurrent包来简化您的工作。

Edit : Misread question, 编辑 :误读的问题,

C# What I normally do is create a Global Static Class and then set the values there. C#我通常要做的是创建一个全局静态类,然后在其中设置值。 That way you can access it from both threads. 这样,您可以从两个线程访问它。 Not sure if this is the preferred method and there could be cases where locking occurs (correct me if I'm wrong) which should be handled. 不知道这是否是首选方法,并且在某些情况下可能发生锁定(如果我错了,请纠正我),应该处理。

I haven't tried it but It should work for for the threadpool/backgroundworker as well. 我还没有尝试过,但它也适用于线程池/ backgroundworker。

我能想到的一种方法是通过属性文件。

Well, it depends a lot on the work that the thread is supposed to do. 好吧,这很大程度上取决于线程应该执行的工作。 For example, you can have a thread waiting for a Event (eg ManualResetEvent) and a shared queue where you put work items (can be data structures to be processed, or more clever commands following a Command pattern). 例如,您可以让一个线程等待一个事件(例如,ManualResetEvent),并在一个共享队列中放置工作项(可以是要处理的数据结构,或者是遵循命令模式的更巧妙的命令)。 Somebody adds new work to the queue ad signals the event, so the trhread awakes, gets work from the queue and start performing its task. 有人将新工作添加到队列中,广告会在事件发生时发出信号,从而使信号唤醒,从队列中获取工作并开始执行其任务。

You can encapsulate this code inside a custom queue, where any thread that calls the Deque methods stops until somebody calls Add(item). 您可以将此代码封装在自定义队列中,在该队列中,任何调用Deque方法的线程都将停止,直到有人调用Add(item)。

On the other hand, maybe you want to rely on .NET ThreadPool class to issue tasks to execute by the threads on the pool. 另一方面,也许您想依靠.NET ThreadPool类来发出要由池中的线程执行的任务。

Does this example help a bit? 这个例子有帮助吗?

您可以使用委托模式,其中子线程订阅事件,而主线程通过传递参数引发事件。

You could run your worker thread within a loop (if that makes sense for your requirement) and check a flag on each execution of the loop. 您可以在一个循环中运行辅助线程(如果这对您的要求有意义),并在每次循环执行时检查一个标志。 The flag would be set by the other thread to signal the worker thread that some state had changed, it could also set a field at the same time to pass the new state. 该标志将由另一个线程设置,以向工作线程发出信号,通知某些状态已更改,它也可以同时设置一个字段以传递新状态。

Additionally, you could use monitor.wait and monitor.pulse to signal the state changes between the threads. 此外,您可以使用monitor.wait和monitor.pulse发出信号,告知线程之间的状态变化。

Obviously, the above would need synchronization. 显然,以上将需要同步。

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

相关问题 将数据传递给showOptionsDialog的正确方法 - Correct way to pass data to showOptionsDialog 在某些情况下终止线程的正确方法是什么? - What is the correct way to terminate thread on some condition? 使线程返回值的正确方法是什么? - What is the correct way to make a thread return a value? 将参数传递给JavascriptExecutor的正确方法是什么? - What is the correct way to pass arguments to the JavascriptExecutor? 有没有办法判断虚拟线程在哪个载体线程上运行? - Is there a way to tell what Carrier Thread a Virtual Thread is running on? 停止线程等待网络活动的正确方法是什么? - What is the correct way to stop a thread waiting for network activity? 在 Firestore 中构建此类数据的正确方法是什么? - What is the correct way to structure this kind of data in Firestore? 将附加参数传递给HTTP @DELETE方法的正确方法是什么 - what is the correct way to pass additional parameter to HTTP @DELETE method 通过引用方法传递参数的正确和最佳方法是什么? - what is the correct and best way to pass argument by reference to a method? 在EDT之外执行长时间运行的正确方法是什么? - What is the correct way to perform long-running operation outside the EDT?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM