7

我对一个简单的代码感到疯狂,我在其中使用 BackgroundWorker 来自动化基本操作。我应该向剪贴板添加内容吗?

在BackgroundWorker的方法中执行这段代码后:

Clipboard.SetText (splitpermutation [i]);

我收到一个错误,说明线程必须是 STA,但我不明白该怎么做。这里有更多代码:(不是全部)

private readonly BackgroundWorker worker = new BackgroundWorker();

private void btnAvvia_Click(object sender, RoutedEventArgs e)
{
    count = lstview.Items.Count;
    startY = Convert.ToInt32(txtY.Text);
    startX = Convert.ToInt32(txtX.Text);
    finalY = Convert.ToInt32(txtFinalPositionY.Text);
    finalX = Convert.ToInt32(txtFinalPositionX.Text);
    incremento = Convert.ToInt32(txtIncremento.Text);
    pausa = Convert.ToInt32(txtPausa.Text);

    worker.WorkerSupportsCancellation = true;
    worker.RunWorkerAsync();

    [...]
}

private void WorkFunction(object sender, DoWorkEventArgs e)
{
    [...]

    if (worker.CancellationPending)
    {
        e.Cancel = true;
        break;
    }
    else
    {
        [...]
        Clipboard.SetText(splitpermutation[i]);
        [...]
    }
}
4

3 回答 3

8

您可以将其编组到 UI 线程以使其工作:

else
{
    [...]
    this.Dispatcher.BeginInvoke(new Action(() => Clipboard.SetText(splitpermutation[i])));
    [...]
}
于 2013-04-09T21:55:35.530 回答
3

BackgroundWorker.NET 线程池上运行。线程池线程在 COM 多线程单元中运行。要使用剪贴板,您必须在单线程单元中运行。您可以创建自己的线程并将其设置为在 STA 中运行,但最好使用Control.Invoke(或BeginInvoke) 返回到用户界面线程(必须是 STA 线程)。

于 2013-04-09T22:00:36.577 回答
0

你得到的例外是因为你试图从 UI 线程外部在 UI 线程上做一些事情(a BackgroundWorker,顾名思义,在后台做一些事情,为此它需要创建一个单独的线程)。

虽然 Reed 发布的答案(即使用Dispatcher.BeginInvoke)是避免此异常的一种方法,但我想知道为什么您首先要尝试从主要工作方法向剪贴板发送内容...

BackgroundWorker公开事件,例如(ProgressChanged您可以从您的工作方法定期调用)或RunWorkerCompleted(当主要工作方法完成时将触发)。

在这些事件中的任何一个中使用Clipboard.SetText都不应该导致您看到的异常,这似乎是在使用BackgroundWorker.

于 2013-04-09T22:01:43.363 回答