7

谁能帮助我我有一个问题我试图通过线程池让这段代码在后台工作,但我似乎无法让它工作我不断收到这个错误:

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

这是我正在使用的代码:

private void DoWork(object o)
{
    var list = ListBox3;

    var request = createRequest(TxtServer.Text, WebRequestMethods.Ftp.ListDirectory);

    using (var response = (FtpWebResponse)request.GetResponse())
    {
        using (var stream = response.GetResponseStream())
        {
            using (var reader = new StreamReader(stream, true))
            {
                while (!reader.EndOfStream)
                {
                    list.Items.Add(reader.ReadLine());
                    ResultLabel.Text = "Connected";
                }
            }
        }
    }
}
4

7 回答 7

9

您可以通过这样做访问控制

 Invoke(new Action(() => {Foo.Text="Hi";}));
于 2012-12-19T06:12:19.157 回答
6

您需要调用委托来更新列表。请参阅此MSDN 示例

于 2012-12-19T03:57:15.020 回答
3

This extension method solves the problem too.

/// <summary>
/// Allows thread safe updates of UI components
/// </summary>
public static void InvokeEx<T>(this T @this, Action<T> action) where T : ISynchronizeInvoke
{
    if (@this.InvokeRequired)
    {
        @this.Invoke(action, new object[] { @this });
    }
    else
    {
        action(@this);
    }
}

Use in your worker thread as follows

InvokeEx(x => x.MyControl.Text = "foo");
于 2014-05-01T11:08:03.343 回答
3

您还可以使用以下语法和 Action 委托通过调用来访问控件:

 Invoke((Action)(() =>
 {
      var myVar = SomeWinFormControl.Property;
 }));
于 2016-10-24T23:24:28.617 回答
2

您不能从单独的线程访问控件,它必须来自创建控件的同一线程。

于 2012-12-19T03:51:56.687 回答
1

我假设这DoWork是在另一个线程上启动的。代码访问ListBox3,这是一个 GUI 控件。.NET 将对 GUI 控件的访问限制为创建它们的线程。

于 2012-12-19T03:53:15.987 回答
1

您可以这样做,因为从 UI 线程以外的其他控件访问控件需要调用。

当您开始时(我假设您使用 BackgroundWorker),将文本框中的 urlRunWorkerAsync(TxtServer.Text)作为参数传递,然后:

private void DoWork(object o, DoWorkEventArgs e)
{
    string Url = (string) e.Argument;

    List<of string> tmpList = new List<of string>;

    var request = createRequest(url, WebRequestMethods.Ftp.ListDirectory);

    using (var response = (FtpWebResponse)request.GetResponse())
    {
        using (var stream = response.GetResponseStream())
        {
            using (var reader = new StreamReader(stream, true))
            {
                while (!reader.EndOfStream)
                {
                    list.Add(reader.ReadLine());
                    //ResultLabel.Text = "Connected";
                    //use reportprogress() instead
                }
            }
        }
    }
    e.result = tmpList;
}

然后在您的 Completed 事件中将 e.result 转换为列表并将其添加到您的控件中。

于 2012-12-19T06:03:17.447 回答