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

これを行うことでcontrollにアクセスできます

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

リストを更新するには、デリゲートを呼び出す必要があります。このMSDNの例を参照してください。

于 2012-12-19T03:57:15.020 に答える
3

この拡張メソッドも問題を解決します。

/// <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);
    }
}

次のようにワーカースレッドで使用します

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

アクションデリゲートで次の構文を使用して、invokeを介してコントロールにアクセスすることもできます。

 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スレッド以外からコントロールにアクセスするにはinvokeが必要なので、代わりにこれを行うことができます。

開始するとき(BackgroundWorkerを使用していると仮定します)、テキストボックスからRunWorkerAsync(TxtServer.Text)引数としてURLを渡してから、次のようにします。

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 に答える