C #: Listbox CrossThreading Проблемы - PullRequest
0 голосов
/ 06 июня 2011

Я пытаюсь получить доступ к 3 элементам списка в моей программе из другого потока и продолжаю получать исключения между потоками.Мне нужен способ получить доступ к моим спискам из другого потока и иметь этот код в отдельном классе с именем threadUtilities.cs.Таким образом, весь код, связанный с доступом к потокам, будет в отдельном классе.Кто-нибудь может предоставить общий код для доступа к любому списку из другого потока?

Ответы [ 2 ]

2 голосов
/ 06 июня 2011

Вы хотите получить SynchronizationContext из потока пользовательского интерфейса и затем сделать его доступным для фоновых потоков.

В зависимости от того, какую технологию вы используете, производное SynchronizationContextбудут доступны, но на самом деле это не касается;свойство Current вернет то, что установлено в данный момент, и Windows Forms и WPF установят для вас нужное.

С SynchronizationContext, переданным нужному потокучтобы совершать вызовы, вы можете затем вызвать метод Send (аналог Invoke метод ) или метод Post (аналогBeginInvoke метод ) в зависимости от ваших потребностей.

Вот пример:

public void Button1_OnClick(sender object, EventArgs e)
{
    // Get the current SynchronizationContext.
    // NOTE: Must make the call on the UI thread, NOT
    // the background thread to get the proper
    // context.
    SynchronizationContext context = SynchronizationContext.Current;

    // Start some work on a new Task (4.0)
    Task.Factory.StartNew(() => { 
        // Do some lengthy operation.
        ...

        // Notify the user.  Do not need to wait.
        context.Post(o => MessageBox.Show("Progress"));

        // Do some more stuff.
        ...

        // Wait on result.
        // Notify the user.
        context.Send(o => MessageBox.Show("Progress, waiting on OK"));
    });
}

Также следует отметить, что BackgroundWorkerкласс делает все это для вас за кулисами;если эта модель вам подходит для непосредственного использования SynchronizationContext, то обязательно используйте это (класс BackgroundWorker использует SynchronizationContext для внутреннего использования).

1 голос
/ 06 июня 2011

Зависит от того, является ли это WinForms или WPF.Если WinForms, используйте метод Control.Invoke.Если WPF, используйте Dispatcher.

Простой пример WinForms:

ListBox listBox = GetListBoxFromSomewhere();
if( listBox.InvokeRequired )
    listBox.Invoke(() => listBox.Items.Add("Some item");
else
    listBox.Items.Add("Some item");

Вы можете сделать универсальную функцию для доступа к пользовательскому интерфейсу, например так:

void PerformUIOperation(Control c, Action action)
{
    if( c.InvokeRequired )
        c.Invoke(action);
    else
        action();
}

Используйте вот так:

PerformUIOperation(listBox, () => listBox.Items.Add("Some item");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...