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

发布于 2024-11-01 03:25:01 字数 381 浏览 2 评论 0原文

在大多数情况下,当您创建线程时,您可以预先准备数据并将其传递到构造函数或方法中。

然而,在像打开套接字连接这样的情况下,您通常已经创建了一个线程,但希望告诉它执行某些操作。

基本思想:

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?

那么在 C# 和 Java 中将数据传递给正在运行的线程的正确方法是什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

那支青花 2024-11-08 03:25:01

将数据传递到正在运行的线程的一种方法是实现消息队列。想要告诉侦听线程执行某些操作的线程会将一个项目添加到侦听线程的队列中。侦听线程以阻塞方式从此线程读取。当没有要执行的操作时使其等待。每当另一个线程将消息放入队列中时,它都会获取该消息,具体取决于项目及其内容,然后您可以对其执行某些操作。

这是一些 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)
      {
        ...
      }
   }
}

调用者:

class Caller
{
  private Listener listener;

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

当然,在编写并行/并发代码时有很多最佳实践。例如,您至少应该添加一个类似于 run :: Bool 的字段,而不是 while(true) ,您可以在收到 StopMessage 时将其设置为 false。根据您想要实现此功能的语言,您将需要处理其他原语和行为。

例如,在 Java 中,您可能需要使用 java.util.Concurrent 包让事情变得简单。

One way to pass data to a running thread is by implementing 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:

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. 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.

屋檐 2024-11-08 03:25:01

Java

你基本上可以有一个LinkedList(一个LIFO< /a>)并继续(进行某些操作)如下(未经测试):

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

当您在其他地方保留对参数中给出的 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();
 }

Java

You could basically have a LinkedList (a LIFO) and proceed (with something) like this (untested) :

 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 :

 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();
 }
强者自强 2024-11-08 03:25:01

编辑:误读问题,

C#
我通常做的是创建一个全局静态类,然后在那里设置值。这样您就可以从两个线程访问它。不确定这是否是首选方法,并且可能存在应该处理的锁定发生的情况(如果我错了,请纠正我)。

我还没有尝试过,但它也应该适用于线程池/后台工作者。

Edit: Misread question,

C#
What I normally do is create a Global Static Class and then set the values there. 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.

囚你心 2024-11-08 03:25:01

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

One way I can think of is through property files.

蓝眼睛不忧郁 2024-11-08 03:25:01

嗯,这在很大程度上取决于线程应该完成的工作。
例如,您可以有一个等待事件(例如ManualResetEvent)的线程和一个放置工作项(可以是要处理的数据结构,或者遵循命令模式的更聪明的命令)的共享队列。有人将新工作添加到队列并发出事件信号,因此 trhread 被唤醒,从队列中获取工作并开始执行其任务。

您可以将此代码封装在自定义队列中,其中调用 Deque 方法的任何线程都会停止,直到有人调用 Add(item)。

另一方面,也许您想依赖 .NET ThreadPool 类来发出任务以由池中的线程执行。

这个例子有一点帮助吗?

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 (e.g. 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). 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).

On the other hand, maybe you want to rely on .NET ThreadPool class to issue tasks to execute by the threads on the pool.

Does this example help a bit?

李白 2024-11-08 03:25:01

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

You can use delegate pattern where child threads subscribes to an event and main thread raises an event, passing the parameters.

梦里°也失望 2024-11-08 03:25:01

您可以在循环中运行工作线程(如果这对您的要求有意义),并在每次执行循环时检查标志。该标志将由另一个线程设置,以向工作线程发出某些状态已更改的信号,它也可以同时设置一个字段来传递新状态。

此外,您可以使用monitor.wait和monitor.pulse来指示线程之间的状态变化。

显然,上面需要同步。

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.

Obviously, the above would need synchronization.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文