这是我当前的后台工作者代码,我希望得到标签,说明它正在下载哪个文件。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string[] FileArray = new string[] {
"configs.pck", "interfaces.pck", "trees.pck", "elementskill.dll",
"reportbugs\\zreportbugs.exe", "userdata\\server\\serverlist.txt",
"userdata\\systemsettings.ini", "data\\aipolicy.data", "data\\domain.data",
"data\\domain1.data", "data\\domain2.data", "data\\domain3.data",
"data\\domain4.data", "data\\dyn_tasks.data", "data\\dynamicobjects.data", "data\\elements.data",
"data\\forbidden_task.txt", "data\\gshop.data", "data\\gshop1.data", "data\\gshop2.data",
"data\\hometowndata", "data\\path.data", "data\\task_npc.data", "data\\tasks.data",
"data\\tasks.data1", "data\\tasks.data2", "data\\tasks.data3", "data\\tasks.data4",
"data\\tasks.data5", "data\\tasks.data6", "data\\tasks.data7", "data\\tasks.data8",
"data\\tasks.data9", "data\\tasks.data10", "data\\tasks.data11", "data\\tasks.data12",
"data\\tasks.data13", "data\\tasks.data14", "data\\tasks.data15", "data\\tasks.data16",
"data\\tasks.data17", "data\\tasks.data18", "data\\tasks.data19", "data\\tasks.data20",
"data\\tasks.data21", "data\\tasks.data22", "data\\tasks.data23", "data\\tasks.data24",
"data\\tasks.data25", "data\\tasks.data26", "data\\tasks.data27", "data\\tasks.data28",
"data\\tasks.data29", "data\\tasks.data30", "data\\tasks.data31", "data\\tasks.data32",
"data\\tasks.data33", "data\\tasks.data34", "data\\tasks.data35", "data\\tasks.data36",
"data\\tasks.data37", "data\\tasks.data38", "data\\tasks.data39", "data\\tasks.data40",
"data\\tasks.data41", "data\\tasks.data42", "data\\tasks.data43", "data\\tasks.data44",
"data\\title_def.lua", "data\\title_def_u.lua", "data\\VIPAward.data"};
foreach (string FileName in FileArray)
{
// The URL to download the file from
string sUrlToReadFileFrom = "http://jd.paradise-gaming.org/Update/element/" + FileName;
// The path to write the file to
string sFilePathToWriteFileTo = Application.StartupPath + "\\element\\" + FileName;
// First, we need to get the exact size (in bytes) of the file we are downloading
Uri url = new Uri("http://jd.paradise-gaming.org/Update/element/" + FileName);
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
response.Close();
// Get last time file was modified
FileSize = response.LastModified;
string LatestWriteTime = Application.StartupPath + "\\element\\" + FileName; //Get most recent time file was saved.
DateTime UserGshop = File.GetLastWriteTime(LatestWriteTime);
UserFileTime = UserGshop;
if (UserFileTime < FileSize)
{
// Gets the size of the file in bytes
Int64 iSize = response.ContentLength;
// Keeps track of the total bytes downloaded so we can update the progress bar
Int64 iRunningByteTotal = 0;
// Use the webclient object to download the file
using (System.Net.WebClient client = new System.Net.WebClient())
{
// Open the file at the remote URL for reading
using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
{
// Using the FileStream object, we can write the downloaded bytes to the file system
Directory.CreateDirectory(Path.GetDirectoryName(sFilePathToWriteFileTo));
using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create))
{
// Loop the stream and get the file into the byte buffer
int iByteSize = 0;
byte[] byteBuffer = new byte[iSize];
while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
// Write the bytes to the file system at the file path specified
streamLocal.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
// Calculate the progress out of a base "100"
double dIndex = (double)(iRunningByteTotal);
double dTotal = (double)byteBuffer.Length;
double dProgressPercentage = (dIndex / dTotal);
int iProgressPercentage = (int)(dProgressPercentage * 100);
// Update the progress bar
backgroundWorker1.ReportProgress(iProgressPercentage);
}
// Clean up the file stream
streamLocal.Close();
}
// Close the connection to the remote server
streamRemote.Close();
}
}
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pBarFileProgress.Value = e.ProgressPercentage;
gbFileProgress.Text = String.Format("Current File Progress: {0} %", e.ProgressPercentage);
lblCheckFile.Text = "Downloaing" + FileName;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnPlay.Enabled = true;
btnFullCheck.Enabled = true;
lblCheckFile.Text = "Download Complete!";
gbFileProgress.Text = "No More Files to Check!";
pBarFileProgress.Value = 0;
}
我尝试在不同时间将lblCheckFile.Text = "Downloaing" + FileName;
放在backgroundworker1_DoWork和Progress_Change上,但Progress_Change只显示“正在下载”,而不是文件名。当我把它放在DoWork下时,它出错并说Exception:Thrown: "Cross-thread operation not valid: Control 'lblCheckFile' accessed from a thread other than the thread it was created on."
答案 0 :(得分:2)
foreach
事件中的DoWork
循环正在动态创建FileName
字符串,以迭代FileArray
字符串数组。在循环之外无法访问它,因此我不确定FileName
事件中以下ProgressChanged
变量的来源:
lblCheckFile.Text = "Downloaing" + FileName;
使用BackgroundWorker构造中内置的组件来报告进度。
来自DoWork
事件:
...
// use the webclient object to download the file
using (System.Net.WebClient client = new System.Net.WebClient())
{
...
// pass the filename as the second argument (change 0 to the correct %)
backgroundWorker1.ReportProgress(0, FileName);
...
在ProgressChanged
事件中,您会获得从e.UserState
传递的价值:
var fileName = Convert.ToString(e.UserState);
lblCheckFile.Text = string.Format("Downloading {0}", fileName);
要完成这项工作,您必须将当前的电话号码移至:
backgroundWorker1.ReportProgress(iProgressPercentage);
并将其与我的电话结合起来:
backgroundWorker1.ReportProgress(iProgressPercentage, FileName);
否则,您将暂时看到标签中显示的文件名片刻,但随后通过iProgressPercentage
的第二个调用将实际传递空值为UserState
,然后将获得转换为空字符串并导致文件名从标签中消失。
答案 1 :(得分:1)
在Windows窗体(以及大多数其他GUI框架)中,您无法从后台线程执行GUI操作。这是您收到的“跨线程操作无效”错误的含义。
为此,您需要使用Invoke()
/ BeginInvoke()
方法在主GUI线程上执行标签更新。如果您的后台线程具有表单句柄,则可以直接执行此操作。否则,一个通用的设计模式是线程引发表单订阅的事件;然后,表单的事件处理程序将使用Invoke / BeginInvoke更新GUI线程上的标签。
另请参阅this discussion of BackgroundWorkers updating GUIs,其中包含有关此解决方案和其他解决方案的更多信息。