我将我的程序分为3层; GUI,BL,IO并尝试将文件从我的服务器抓取到我的电脑上。我使它多线程和zorks很好,但当我试图添加一个委托给它从我的IO发送消息到我的GUI,它麻烦我。它说的是:
不允许通过各种线程执行操作:它 是从另一个线程有权访问控件标签下载 进度而不是创建元素的线程。
我拥有的是:
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;
}
BL
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) { }
}
Delgate
public delegate void ObserverDelegate(string fileName);
答案 0 :(得分:1)
假设标签更新失败,您需要将事件编组到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);
}
答案 1 :(得分:0)
如果某个控制代码文件中有UpdateDownloadLabel
函数,请使用如下模式:
private void UpdateDownloadLabel(string File)
{
this.Invoke(new Action(()=> {
labelDownloadProgress.Text = "Downloading: " + File;
})));
}
您需要在UI线程上调用赋值,以便能够更改标签上的内容。