В C#, каков рекомендуемый способ передать данные между 2 потоками?

Если вы используете сервлеты или класс действия для создания своего списка, а затем перенаправляете его на свой JSP, вы должны иметь следующую строку в своем сервлете или классе действий.

ArrayList<Person> names = "get from somewhere";

request.setAttribute("personNames",names);  

<c:foreach var="item" items="${personNames}"> ${item.title} </c:foreach>
25
задан Jon Tackabury 2 December 2008 в 19:14
поделиться

8 ответов

. Сеть уже идет System.ComponentModel.BackgroundWorker класс конкретно для справлений с работающими фоновыми задачами и связывающийся с GUI. Используйте его.

12
ответ дан Dour High Arch 15 October 2019 в 15:14
поделиться

Ничего себе, я не могу верить, как может, люди не потрудились читать вопрос.

Так или иначе, это - то, что я делаю.

  1. Создают Вас классы "сообщения". Это хранит всю информацию, которой Вы хотите поделиться.
  2. Создают Queue< T> для каждого потока. Используйте SyncLock (блокировка C#) к чтению-записи к нему.
  3. , Когда Вы хотите говорить с потоком, отправьте ему объект сообщения с копия из всей информации, в которой требуется путем добавления сообщения к очереди.
  4. рабочий поток может тогда читать из очереди, читая и обрабатывая каждое сообщение в порядке. Когда нет никаких сообщений, просто не спят.

Удостоверяются, что Вы не совместно используете объекты между двумя потоками. Как только Ваш поток GUI прикрепляет сообщение в Очередь, поток GUI больше не владеет сообщением. Это не может содержать ссылку на сообщение, или Вы вовлечете себя в проблему.

Это не даст Вам самую лучшую производительность, но это будет достаточно хорошо для большинства приложений. И что еще более важно, это сделает его намного тяжелее, чтобы сделать ошибку.

ОБНОВЛЕНИЕ: не используйте SyncLock и Очередь. Вместо этого используйте ConcurrentQueue, который обработает любую блокировку автоматически для Вас. Вы получите лучшую производительность и, менее вероятно, сделаете ошибку.

39
ответ дан Jonathan Allen 15 October 2019 в 15:14
поделиться

В действительности Вы создали версию бедного человека ThreadPool. Ваш второй поток просто находится, там ничего не делая и без изрядного количества работы с Вашей стороны, Вы не можете только заставить его делать работу для Вас. Необходимо было бы передать делегатов в очередь, которую поток тогда снимает и выполняет.

Ваш лучший выбор состоит в том, чтобы сделать то, что Вы предназначили, и просто используйте.NET ThreadPool и дайте ему работу, чтобы сделать.

6
ответ дан Rob Prouse 15 October 2019 в 15:14
поделиться

Я предполагаю, что некоторое событие в GUI требует некоторой продолжительной задачи запуститься, которые выполняются в фоновом режиме - существует два основных способа сделать это. Если Вы просто хотите назвать метод на различном потоке тогда, можно сделать это Звонящие Синхронные Методы Асинхронно . Я обычно делаю что-то вроде этого:



//delegate with same prototype as the method to call asynchrously
delegate void ProcessItemDelegate(object item);

//method to call asynchronously
private void ProcessItem(object item) { ... }

//method in the GUI thread
private void DoWork(object itemToProcess)
{
    //create delegate to call asynchronously...
    ProcessItemDelegate d = new ProcessItemDelegate(this.ProcessItem);
    IAsyncResult result = d.BeginInvoke(itemToProcess,
                                        new AsyncCallback(this.CallBackMethod),
                                        d); 
}

//method called when the async operation has completed
private void CallbackMethod(IAsyncResult ar)
{
    ProcessItemDelegate d = (ProcessItemDelegate)ar.AsyncState;
    //EndInvoke must be called on any delegate called asynchronously!
    d.EndInvoke(ar);
}

знать при использовании этого метода, что обратный вызов выполняется на фоновом потоке, таким образом, любые обновления GUI должны быть сделаны с помощью, Вызывают.

, Кроме того, Вы могли использовать общее состояние, чтобы связаться между потоками и использовать EventWaitHandle для передачи сигналов об обновлениях общего состояния - в этом примере, метод в GUI добавляет объекты работы к очереди, чтобы быть обработанным в фоновом режиме. Рабочий поток обрабатывает объекты от очереди, когда работа становится доступной.


//shared state
private Queue workQueue;
private EventWaitHandle eventHandle;

//method running in gui thread
private void DoWork(Item itemToProcess)
{
   //use a private lock object instead of lock...
   lock(this.workQueue)
   {
       this.workQueue.Add(itemToProcess);
       this.eventHandle.Set();
   }
}

//method that runs on the background thread
private void QueueMonitor()
{
   while(keepRunning)
   {
       //if the event handle is not signalled the processing thread will sleep here until it is signalled or the timeout expires
       if(this.eventHandle.WaitOne(optionalTimeout))
       {
           lock(this.workQueue)
           {
              while(this.workQueue.Count > 0)
              {
                 Item itemToProcess = this.workQueue.Dequeue();
                 //do something with item...
              }
           }
           //reset wait handle - note that AutoResetEvent resets automatically
           this.eventHandle.Reset();
       }
   }
}
3
ответ дан Lee 15 October 2019 в 15:14
поделиться

Удобство Управления. От BeginInvoke () трудно отказаться. Вы не имеете к. Добавьте новый класс к своему проекту и вставьте этот код:

using System;
using System.Threading;
using System.Windows.Forms;

public partial class frmWorker : Form {
  public frmWorker() {
    // Start the worker thread
    Thread t = new Thread(new ParameterizedThreadStart(WorkerThread));
    t.IsBackground = true;
    t.Start(this);
  }
  public void Stop() {
    // Synchronous thread stop
    this.Invoke(new MethodInvoker(stopWorker), null);
  }
  private void stopWorker() {
    this.Close();
  }
  private static void WorkerThread(object frm) {
    // Start the message loop
    frmWorker f = frm as frmWorker;
    f.CreateHandle();
    Application.Run(f);
  }
  protected override void SetVisibleCore(bool value) {
    // Shouldn't become visible
    value = false;
    base.SetVisibleCore(value);
  }
}

Вот некоторый пример кода для тестирования его:

  public partial class Form1 : Form {
    private frmWorker mWorker;
    public Form1() {
      InitializeComponent();
      mWorker = new frmWorker();
    }

    private void button1_Click(object sender, EventArgs e) {
      Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
      mWorker.BeginInvoke(new MethodInvoker(RunThisOnThread));
    }
    private void RunThisOnThread() {
      Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
    }

    private void button2_Click(object sender, EventArgs e) {
      mWorker.Stop();
    }
  }
2
ответ дан Hans Passant 15 October 2019 в 15:14
поделиться

Используйте объект синхронизации для передачи сигналов о потоке, что он должен обработать новые данные (или новое состояние GUI). Один относительно простой способ сделать это должно использовать объект-событие. Вот краткое изложение того, как это работало бы:

  1. поток GUI 2-я доля потока объект-событие (таким образом, они оба знают об этом)
  2. 2-й поток обычно работает в каком-то цикле, и каждый раз, когда это ожидает события, которое будет сообщено
  3. , поток GUI сигнализирует о событии, когда этому нужен 2-й поток, чтобы сделать что-то
  4. , Когда 2-й поток сделан, это сбрасывает событие и ожидает снова (или выходы)
1
ответ дан Brian 15 October 2019 в 15:14
поделиться

Поместите цикл в свой второй поток, который спит большую часть времени, но каждый [Интервал] он просыпается и проверяет совместно используемую переменную, которая говорит его, выполнить ли Ваш метод или нет, и если та общая булевская переменная имеет значение true, то он выполняет метод, который выполняет любую задачу, которую Вы пытаетесь выполнить... В том методе имейте метод, собирают данные, требуемые от другой совместно используемой переменной.

В основном потоке GUI, помещенном данные в совместно используемую переменную параметра метода, затем устанавливает булеву совместно используемую переменную "Выполнения" на истинный...

Внутренняя часть метод рабочего, не забудьте сбрасывать общий bool "выполненная" переменная ко лжи, когда Вы будете сделаны, таким образом, выигранный цикл; t выполняют тот же экземпляр много раз...

1
ответ дан Charles Bretana 15 October 2019 в 15:14
поделиться

Можно использовать события или как Grauenwolf заявил - сигнал сообщения. Я обертываю каждый свой поток как одиночный элемент управления, оттуда можно реализовать любого легко. Вы могли даже сделать плохие общественные собственности человека для зеркального отражения битов.

Также Вы могли реализовать конечный автомат, и вместо передачи обменивается сообщениями, каждый поток мог контролировать друг друга

1
ответ дан dfasdljkhfaskldjhfasklhf 15 October 2019 в 15:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: