Пул потоков: операция с несколькими потоками недопустима. - PullRequest
4 голосов
/ 29 декабря 2011

Я довольно нов, когда дело доходит до многопоточности, но я получаю InvalidOperationException при использовании следующего кода. Я понимаю, что он пытается получить доступ к importFileGridView, но он был создан потоком пользовательского интерфейса, который создает исключение. У меня вопрос, как мне решить эту проблему? Возможно ли, чтобы GetAllImports имел тип возвращаемого значения? Как получить доступ к temp из моего потока пользовательского интерфейса?

ThreadPool.QueueUserWorkItem(new WaitCallback(GetAllImports), null);

private void GetAllImports(object x)
    {
        DataSet temp = EngineBllUtility.GetAllImportFiles(connectionString);
        if (temp != null)
            importFileGridView.DataSource = temp.Tables[0];
        else
            MessageBox.Show("There were no results. Please try a different search", "Unsuccessful", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

Ответы [ 2 ]

2 голосов
/ 29 декабря 2011

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

Вы можете справиться с этим через Control.Invoke или Control.BeginInvoke, вот так:

private void GetAllImports(object x)
{
    DataSet temp = EngineBllUtility.GetAllImportFiles(connectionString);
    if (temp != null)
    {
        // Use Control.Invoke to push this onto the UI thread
        importFileGridView.Invoke((Action) 
            () => 
            {
                importFileGridView.DataSource = temp.Tables[0];
            });
    }
    else
        MessageBox.Show("There were no results. Please try a different search", "Unsuccessful", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
0 голосов
/ 29 декабря 2011

Что сказал Рид, но мне нравится этот синтаксис немного лучше:

Что происходит, когда вы создаете функцию делегата, которая будет передаваться в качестве параметра в поток пользовательского интерфейса через Control.Invoke, который ее вызывает, таким образом, поток пользовательского интерфейса вносит изменения в importFileGridView.

importFileGridView.Invoke((MethodInvoker) delegate {
                             importFileGridView.DataSource = temp.Tables[0];
                         });

Вы также можете написать это так:

//create a delegate with the function signature
public delegate void SetDateSourceForGridViewDelegate (GridView gridView, Object dataSource);

//write a function that will change the ui
public void SetDataSourceForGridView(GridView gridView, Object dataSource)
{
    gridView.DataSource = dataSource;
}

//Create a variable that will hold the function
SetDateSourceForGridViewDelegate delegateToInvoke = SetDataSourceForGridView;

//tell the ui to invoke the method stored in the value with the given paramters.
importFileGridView.Invoke(delegateToInvoke, importFileGridView, temp.Tables[0]);

и я бы посоветовал использовать MethodInvoker сверх Action см .: здесь

...