C#Backgroundworker在标签中下载进度,在标签中获取字节
我已经创建了一个应用程序来修补我的游戏服务器文件。 然而,我有三个问题无法解决:C#Backgroundworker在标签中下载进度,在标签中获取字节,c#,C#,我已经创建了一个应用程序来修补我的游戏服务器文件。 然而,我有三个问题无法解决: 下载新补丁时,它不会立即更新progressbar,但会在大约30-40秒后刷新它 我想要一个标签来显示他们下载了多少兆字节,以及到目前为止有多少兆字节(例如:122Mb/750Mb) 下载时,我想要一个标签来显示~%的下载量 我不知道如何添加数字2和3,而数字1的问题似乎很可笑,因为在我的编码中,没有任何东西表明它应该在30-40秒后刷新(至少据我所知) 我的背景工作: private void backgrou
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Defines the server's update directory
string Server = "http://localhost/dl/game-updates/";
//Defines application root
string Root = AppDomain.CurrentDomain.BaseDirectory;
//Make sure version file exists
FileStream fs = null;
if (!File.Exists("version"))
{
using (fs = File.Create("version"))
{
}
using (StreamWriter sw = new StreamWriter("version"))
{
sw.Write("1.0");
}
}
//checks client version
string lclVersion;
using (StreamReader reader = new StreamReader("version"))
{
lclVersion = reader.ReadLine();
}
decimal localVersion = decimal.Parse(lclVersion);
//server's list of updates
XDocument serverXml = XDocument.Load(@Server + "Updates.xml");
//The Update Process
foreach (XElement update in serverXml.Descendants("update"))
{
string version = update.Element("version").Value;
string file = update.Element("file").Value;
decimal serverVersion = decimal.Parse(version);
string sUrlToReadFileFrom = Server + file;
string sFilePathToWriteFileTo = Root + file;
if (serverVersion > localVersion)
{
Uri url = new Uri(sUrlToReadFileFrom);
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
response.Close();
Int64 iSize = response.ContentLength;
Int64 iRunningByteTotal = 0;
using (System.Net.WebClient client = new System.Net.WebClient())
{
using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
{
using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
{
int iByteSize = 0;
byte[] byteBuffer = new byte[iSize];
while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
{
streamLocal.Write(byteBuffer, 0, iByteSize);
iRunningByteTotal += iByteSize;
double dIndex = (double)(iRunningByteTotal);
double dTotal = (double)byteBuffer.Length;
double dProgressPercentage = (dIndex / dTotal);
int iProgressPercentage = (int)(dProgressPercentage * 100);
backgroundWorker1.ReportProgress(iProgressPercentage);
}
streamLocal.Close();
}
streamRemote.Close();
}
}
//unzip
using (ZipFile zip = ZipFile.Read(file))
{
foreach (ZipEntry zipFiles in zip)
{
zipFiles.Extract(Root + "\\", true);
}
}
//download new version file
WebClient webClient = new WebClient();
webClient.DownloadFile(Server + "version.txt", @Root + "version");
//Delete Zip File
deleteFile(file);
}
}
}
我的背景工作1\u进度发生了变化:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
label1.Text = "Downloading updates...";
}
我的后台工作人员1_runworker已完成:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
settings_btn.Enabled = true;
start_btn_disabled.Enabled = false;
start_btn_disabled.Visible = false;
start_btn.Visible = true;
start_btn.Enabled = true;
progressBar1.Value = 100;
label1.Text = "Client is up to date!";
}
还有一个附带说明:我在backgroundWorker2\u DoWork中更新标签时也遇到了一些问题?
有什么想法吗?我想这是因为您试图在不同的线程上更新UI对象。如果使用wpf,您是否尝试过使用Dispatcher 如果使用Winforms,是否调用 编辑:
正如@daylight指出的那样,UI在progresschanged事件中被更新,该事件在创建后台工作线程的线程上执行,因此线程方面不应该存在问题。有关更多信息,请参阅这里的一些工作代码,使用BackgroundWorker更新Form1上的标签 创建一个新的Windows窗体项目,并将其放入您的代码中,它就会工作。 它非常难看,但很管用。 之后,只需将代码插入DoWork方法,计算值并发送到ReportProgress 请记住,DoWork方法中完成的工作是实际的后台线程。 这意味着在该方法(DoWork)中,您无法访问UI(表单)元素,因为它们位于UI线程上
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button1.Enabled = true;
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
backgroundWorker1.RunWorkerAsync();
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
}
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
FakeCountingWork();
}
private void FakeCountingWork()
{
int totalNumber = 100;
int progressCounter = 0;
while (progressCounter < totalNumber)
{
int fakecounter = 0;
for (int x = 0; x < 100000000; x++)
{
fakecounter++;
}
progressCounter++;
backgroundWorker1.ReportProgress(progressCounter);
}
}
}
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
backgroundWorker1.DoWork+=backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged+=backgroundWorker1\u ProgressChanged;
backgroundWorker1.WorkerReportsProgress=true;
backgroundWorker1.RunWorkerCompleted+=backgroundWorker1\u RunWorkerCompleted;
}
void backgroundWorker1\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
{
按钮1.启用=真;
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
按钮1.启用=错误;
backgroundWorker1.RunWorkerAsync();
}
void backgroundWorker1\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
label1.Text=e.ProgressPercentage.ToString();
}
无效backgroundWorker1\u DoWork(对象发送方,DoWorkerVentargs e)
{
伪造计数工作();
}
私人无效伪造计数工作()
{
整数总数=100;
int progressCounter=0;
while(progressCounter
##################################编辑以添加其他功能
好的,下面是如何实现一个标签,显示到目前为止下载的字节数。
将名为label2的第二个标签添加到表单中。接下来,从我前面的示例中修改以下方法。 在这里,我们将使用UserState向ProgressChanged事件传递一个额外的值。这非常简单。您可以看到我正在生成一个随机数,它现在将出现在Label2中。您可以在这里显示字节数
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.ProgressPercentage.ToString();
label2.Text = e.UserState.ToString();
}
private void FakeCountingWork()
{
int totalNumber = 100;
int progressCounter = 0;
Random rnd = new Random();
while (progressCounter < totalNumber)
{
int fakecounter = 0;
for (int x = 0; x < 100000000; x++)
{
fakecounter++;
}
progressCounter++;
updateValue = rnd.Next();
backgroundWorker1.ReportProgress(progressCounter,updateValue);
}
}
void backgroundWorker1\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
{
label1.Text=e.ProgressPercentage.ToString();
label2.Text=e.UserState.ToString();
}
私人无效伪造计数工作()
{
整数总数=100;
int progressCounter=0;
随机rnd=新随机();
while(progressCounter
此网站上的欢迎可能重复。John。如果你想有更好的机会得到回答,请看以下内容:@demonplus该帖子上的人正在使用backgroundworker插入mysql值。我不是。你应该先阅读该帖子,然后再说这是一个duplicate@JohnK当有人建议复制时,可能意味着其中有代码对你有用的问题-我认为你错了。你的问题部分是关于在使用
BackgroundWorker
时更新标签的,这与链接的问题相同。哦,我的错。对不起,@demonplus。我认为@demonplus发布的链接会有帮助。不管后台工作人员在做什么,它都是有用的是一个与UI对象所在线程不同的线程,所以你不能像平常一样更新它们。实际上,他似乎正在更新UI线程对象(标签)仅在ProgressChanged事件中这样做是正确的。使用ProgressChanged事件更新UI元素是正确的方法,您可以在我更新表单标签的答案中看到这一点。您无法从DoWork()访问UI(表单)元素方法---这是一个单独的执行线程,将失败。@daylight