invalidOperationException 在线程中使用委托时

本文关键字:线程 invalidOperationException | 更新日期: 2023-09-27 18:31:11

>我将我的程序分为 3 层;GUI,BL,IO并尝试将文件从我的服务器抓取到我的PC。我使它成为多线程并且 zorks 很好,但是当我尝试向其添加一个委托以将消息从我的 IO 发送到我的 GUI 时,它让我感到不安。它说的是这样的:

不允许通过各种线程执行操作:它 来自另一个线程有权访问控制标签下载 进度比创建元素的线程要长。

我拥有的是这个:

图形用户界面

private void buttonDownload_Click(object sender, EventArgs e)
{
    download = new BL_DataTransfer(Wat.FILM, titel, this.downloadDel);
    t = new Thread(new ThreadStart(download.DownLoadFiles));    
    t.Start();
}
private void UpdateDownloadLabel(string File)
{
        labelDownloadProgress.Text = "Downloading: " + File;
}

提单

    public void DownLoadFiles()
    {
        //bestanden zoeken op server
        string map = BASEDIR + this.wat.ToString() + @"'" + this.titel + @"'";
        string[] files = IO_DataTransfer.GrapFiles(map);
        //pad omvormen
        string[] downloadFiles = this.VeranderNaarDownLoadPad(files,this.titel);
        IO_DataTransfer.DownloadFiles(@".'" + this.titel + @"'", files, downloadFiles, this.obserdelegate);
    }

IO

    public static void DownloadFiles(string map, string[] bestanden, string[] uploadPlaats, ObserverDelegate observerDelegete)
    {
        try
        {
            Directory.CreateDirectory(map);
            for (int i = 0; i < bestanden.Count(); i++)
            {
                observerDelegete(bestanden[i]);
                File.Copy(bestanden[i], uploadPlaats[i]);
            }
        }
        catch (UnauthorizedAccessException uoe) { }
        catch (FileNotFoundException fnfe) { }
        catch (Exception e) { }        
    }

德尔盖特

 public delegate void ObserverDelegate(string fileName);

invalidOperationException 在线程中使用委托时

假设是标签的更新失败,则需要将事件封送到 UI 线程上。为此,请将更新代码更改为:

private void UpdateDownloadLabel(string File)
{
    if (labelDownloadProgress.InvokeRequired)
    {
        labelDownloadProgress.Invoke(new Action(() =>
            {
                labelDownloadProgress.Text = "Downloading: " + File;
            });
    }
    else
    {
        labelDownloadProgress.Text = "Downloading: " + File;
    }
}

我最终为此创建了一个可以调用的扩展方法 - 从而减少了应用程序中重复代码的数量:

public static void InvokeIfRequired(this Control control, Action action)
{
    if (control.InvokeRequired)
    {
        control.Invoke(action);
    }
    else
    {
        action();
    }
}

然后这样称呼:

private void UpdateDownloadLabel(string File)
{
    this.labelDownloadProgress.InvokeIfRequired(() =>
       labelDownloadProgress.Text = "Downloading: " + File);
}

如果UpdateDownloadLabel函数位于某个控件代码文件中,请使用如下模式:

private void UpdateDownloadLabel(string File)
{
     this.Invoke(new Action(()=> {
             labelDownloadProgress.Text = "Downloading: " + File;
      })));
}

您需要在 UI 线程上调用分配,以便能够更改标签上的某些内容。