2014-01-21 3 views
2

Короткая версия:передачи данных между нитями переменного приложения # WinForms

Мне нужно передать сложные данные взад и вперед между нитями, 1 нить будучи WinForm, другой поток, вызывая сервис онлайн-переводчик и изменяющийся все данные используется Winform.

Long Version:

Передача больших объемов данных в сервис онлайн-переводчик замерзал мой передний конец для минут за один раз, так что я пытаюсь переместить эту логику в нить. Winform широко использует данные, которые онлайн-служба должна обрабатывать и возвращать с помощью новой информации.

Я использую этот код, чтобы начать тему:

threadWork tw = new threadWork(); //obj to hold data for thread 
tw.settings = frmMain.projectSettings; 
tw.CompletedEvent += tw_CompletedEvent; // callback event, returns data 
ThreadPool.QueueUserWorkItem(doWork,tw); // kick off thread 

принимающего код обратного вызова:

void tw_CompletedEvent(projectFormat settings) 
{ 
    frmMain.projectSettings = settings; 
    NotifyLoadTransationKeys(frmMain.projectSettings.translationKeys,frmMain.projectSettings.translatedLanguages); 

} 

, которые в основном создали эту ошибку:

Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on. [on frmMain] 

так я нашел this предлагая альтернативное использование [STAThread] [sta = single thread apartment] ins язь Program.cs (по умолчанию точка C# WinForm запись)

using System.Threading; 
Thread t = new Thread(new ThreadStart(StartNewStaThread)); 
// Make sure to set the apartment state BEFORE starting the thread. 
t.ApartmentState = ApartmentState.STA; 
t.Start(); 
private void StartNewStaThread() { 
    Application.Run(new Form1()); 
} 

Все в моей C# приложение запускается в 'Program.cs', поэтому я попытался выше предложение следующим образом:

static class Program 
{ 
    public static translationUtil TranslationUtil; //location of time intensive webservice 
    public static projectFormat projectSettings; //data that needs sharing 

    static void Main() // prog entry point 
    {    
     ProgramCode pc = new ProgramCode(); 
     pc.Main(); 
    } 
} 

class ProgramCode 
{ 
    public void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false);    

     Thread t = new Thread(new ThreadStart(StartNewStaThread)); 
     t.ApartmentState = ApartmentState.STA; 
     t.Start(); 
    } 

    private void StartNewStaThread() 
    { 
     Application.Run(new Main()); 
    } 
} 

в коде выше Я попытался переместить общие ресурсы в «Program.cs», а затем создал новый класс и поток для хранения моей winform, но это все равно дает мне проблемы с перекрестными потоками (такая же ошибка, как раньше)! Кто-нибудь получил предложения относительно использования потоков и совместного использования данных в моей ситуации?

Update: @HenkHolterman ответил на мой вопрос лучше до сих пор, но я пришел через этот код много раз после исследования ответа он дал мне (с помощью «вызова»)

if (control.InvokeRequired) { 
     control.Invoke(new ControlStringConsumer(SetText), new object[]{control, text}); // invoking itself 
    } else { 
     control.Text=text;  // the "functional part", executing only on the main thread 
    } 

Следуйте на вопрос. .. Вышеприведенное выше выражение «if» просто устанавливает текст без вызова (на одной из ветвей «if», следует ли мне следовать этому шаблону, что это такое?

+0

Ошибка не имеет ничего общего с моделью квартиры. Речь идет о простой кросс-резьбе. –

+0

см. Использование InvokeRequired для поточного безопасного вызова http://msdn.microsoft.com/en-us/library/ms171728(v=vs.85).aspx или http://social.msdn.microsoft.com/Forums/vstudio/en-US/296f8e39-fa62-4540-942a-26a53da0896a/threading-invokerequired? forum = csharpgeneral – Jade

ответ

1

Ваше основное решение:

void tw_CompletedEvent(projectFormat settings) 
{ 
    frmMain.projectSettings = settings; 
    frmMain.Invoke(() => 
     NotifyLoadTransationKeys(
      frmMain.projectSettings.translationKeys, 
      frmMain.projectSettings.translatedLanguages) 
    ); 

} 

Но когда NotifyLoadTransationKeys() занимает много времени, вам нужно будет разбить его.

Edit:

призывает к Invoke() часто окружают if (control.InvokeRequired), небольшой оптимизации. Но когда вы уверены, что находитесь на другом (чем в UI) потоке, вы можете пропустить это.

+0

Спасибо, это зафиксировало сообщения об ошибках перекрестной резьбы, которые я получал.Я добавил следующий вопрос, если вы хотите взглянуть. – Nnoel

Смежные вопросы