Can anyone tell me if it is possible(and give an example if it is) on how to have a progress bar(and status label if possible) showing the progress of a ZIP file being extracted using "ZipFile"(Ionic.zip, http://dotnetzip.codeplex.com/)?
My WinForm does a great job at extracting a ZIP file from my chosen path to a new path no worries at all using textboxes and browse buttons and all that jazz... However the only issue is i cannot use anything on my form during this time it is as if it has frozen, but its only because its unzipping the ZIP file in the background.
The ZIP file is a big file and i would like to make it less confusing on what is going on by adding and having a progress bar showing how the unzipping is going with a accurate ETA.
Surely this is possible, i just cannot work out how to do it in C# WinForms, i have had a fairly decent look all around the net without really being able to come across a example i can find suitable for me.
Here is a rough example of what i have:
private void button1_Click(object sender, EventArgs e)
{
var ROBOT0007 = textBox1.Text + #"\" + "ROBOT0007"; //ROBOT0007 folder
var ROBOT_INSTALL = textBox1.Text + #"\" + "911" + #"\" + "files"; //ROBOT0007/911/files
var ROBOT_INSTALL_SPECIAL = ROBOT_INSTALL + #"\" + "special.rar"; //ROBOT0007/911/files/special.rar
//If the path has text...
if (textBox1.TextLength > 0)
{
//if the subfolder doesn't exist then make it.
if (!Directory.Exists(ROBOT0007))
{
Directory.CreateDirectory(ROBOT0007);
}
//if the textbox directory exists
if (Directory.Exists(ROBOT0007))
{
using (ZipFile zip = ZipFile.Read(ROBOT_INSTALL_SPECIAL))
{
zip.ExtractAll(ROBOT0007, ExtractExistingFileAction.OverwriteSilently);
}
}
}
}
UPDATE(04/11/2014): I have removed the textbox for now gone back to simple basics, the following works with a background worker, however the cancel button has no effect on RAR files... any advice?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Threading;
using System.Text;
using System.Windows.Forms;
using Ionic.Zip;
using System.IO;
namespace BackgroundWorkerSample
{
// The BackgroundWorker will be used to perform a long running action
// on a background thread. This allows the UI to be free for painting
// as well as other actions the user may want to perform. The background
// thread will use the ReportProgress event to update the ProgressBar
// on the UI thread.
public partial class Form1 : Form
{
/// <summary>
/// The backgroundworker object on which the time consuming operation
/// shall be executed
/// </summary>
BackgroundWorker backgroundWorker1;
public Form1()
{
InitializeComponent();
backgroundWorker1 = new BackgroundWorker();
// Create a background worker thread that ReportsProgress &
// SupportsCancellation
// Hook up the appropriate events.
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler
(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler
(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
}
/// <summary>
/// On completed do the appropriate task
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// The background process is complete. We need to inspect
// our response to see if an error occurred, a cancel was
// requested or if we completed successfully.
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
// Check to see if an error occurred in the background process.
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
// Everything completed normally.
lblStatus.Text = "Task Completed...";
}
//Change the status of the buttons on the UI accordingly
btnStart.Enabled = true;
btnCancel.Enabled = false;
}
/// <summary>
/// Notification is performed here to the progress bar
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// This function fires on the UI thread so it's safe to edit
// the UI control directly, no funny business with Control.Invoke :)
// Update the progressBar with the integer supplied to us from the
// ReportProgress() function.
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
}
/// <summary>
/// Time consuming operations go here </br>
/// i.e. Database operations,Reporting
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// The sender is the BackgroundWorker object we need it to
// report progress and check for cancellation.
//NOTE : Never play with the UI thread here...
for (int i = 0; i < 100; i++)
{
//Thread.Sleep(100);
string INSTALL_FOLDER= "C:" + #"\" + "Program Files (x86)" + #"\" + "Robot91111"+ #"\" + "basic" + #"\" + "string" + #"\" + "special.rar";
string BURGOS_FOLDER = "C:" + #"\" + "Program Files (x86)" + #"\" + "Robot91111" + #"\" + "Burgos_Folder";
if (!Directory.Exists(BURGOS_FOLDER))
{
Directory.CreateDirectory(BURGOS_FOLDER);
using (ZipFile zip = ZipFile.Read(INSTALL_FOLDER))
{
zip.ExtractAll(BURGOS_FOLDER, ExtractExistingFileAction.OverwriteSilently);
}
}
// Periodically report progress to the main thread so that it can
// update the UI. In most cases you'll just need to send an
// integer that will update a ProgressBar
backgroundWorker1.ReportProgress(i);
// Periodically check if a cancellation request is pending.
// If the user clicks cancel the line
// m_AsyncWorker.CancelAsync(); if ran above. This
// sets the CancellationPending to true.
// You must check this flag in here and react to it.
// We react to it by setting e.Cancel to true and leaving
if (backgroundWorker1.CancellationPending)
{
// Set the e.Cancel flag so that the WorkerCompleted event
// knows that the process was cancelled.
e.Cancel = true;
backgroundWorker1.ReportProgress(0);
return;
}
}
//Report 100% completion on operation completed
backgroundWorker1.ReportProgress(100);
}
private void btnStartAsyncOperation_Click(object sender, EventArgs e)
{
//Change the status of the buttons on the UI accordingly
//The start button is disabled as soon as the background operation is started
//The Cancel button is enabled so that the user can stop the operation
//at any point of time during the execution
btnStart.Enabled = false;
btnCancel.Enabled = true;
// Kickoff the worker thread to begin it's DoWork function.
backgroundWorker1.RunWorkerAsync();
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy)
{
// Notify the worker thread that a cancel has been requested.
// The cancel will not actually happen until the thread in the
// DoWork checks the backgroundWorker1.CancellationPending flag.
backgroundWorker1.CancelAsync();
}
}
}
}
/*...*/
using (ZipFile zip = ZipFile.Read(ROBOT_INSTALL_SPECIAL))
{
zip.ExtractProgress +=
new EventHandler<ExtractProgressEventArgs>(zip_ExtractProgress);
zip.ExtractAll(ROBOT0007, ExtractExistingFileAction.OverwriteSilently);
}
/*...*/
void zip_ExtractProgress(object sender, ExtractProgressEventArgs e)
{
if (e.TotalBytesToTransfer > 0)
{
progressBar1.Value = Convert.ToInt32(100 * e.BytesTransferred / e.TotalBytesToTransfer);
}
}
private int totalFiles;
private int filesExtracted;
/*...*/
using (ZipFile zip = ZipFile.Read(ROBOT_INSTALL_SPECIAL))
{
totalFiles = zip.Count;
filesExtracted = 0;
zip.ExtractProgress += ZipExtractProgress;
zip.ExtractAll(ROBOT0007, ExtractExistingFileAction.OverwriteSilently);
}
/*...*/
private void ZipExtractProgress(object sender, ExtractProgressEventArgs e)
{
if (e.EventType != ZipProgressEventType.Extracting_BeforeExtractEntry)
return;
filesExtracted++;
progressBar.Value = 100 * filesExtracted / totalFiles;
}
using System.IO.Compression;
private async void Unzip(string filePath)
{
var _downloadPath = configuration.GetValue("DownloadPath");
var _extractPath = configuration.GetValue("ExtractPath");
var _extractPattern = configuration.GetValue("ExtractPattern");
Console.WriteLine($"Удаление старых файлов из директории: '{_extractPath}'");
var directoryInfo = new DirectoryInfo(_extractPath);
foreach (var file in directoryInfo.GetFiles())
{
file.Delete();
}
Console.WriteLine($"Распаковка файла: '{filePath}'");
var regex = new Regex(_extractPattern);
var fileList = new List();
var totalFiles = 0;
var filesExtracted = 0;
using (var archive = await Task.Run(() => ZipFile.OpenRead(filePath)))
{
foreach (var file in archive.Entries)
{
if (regex.IsMatch(file.Name))
{
fileList.Add(file);
totalFiles++;
}
}
foreach (var file in fileList)
{
Console.WriteLine($"Извлечение файла: '{file.Name}'");
await Task.Run(() =>
{
file.ExtractToFile($"{_extractPath}{file.Name}");
filesExtracted++;
var progress = Convert.ToInt32(100 * filesExtracted / totalFiles);
Console.WriteLine($"Извлечено: {progress}%");
});
}
}
}
appsettings.json example
{
"DownloadPath": "f:\\download\\",
"ExtractPath": "f:\\download\\extract\\",
"ExtractPattern": "ACTSTAT.DBF|CENTERST.DBF|CURENTST.DBF|ESTSTAT.DBF|FLATTYPE.DBF|NDOCTYPE.DBF|OPERSTAT.DBF|ROOMTYPE.DBF|SOCRBASE.DBF|STRSTAT.DBF|[A-Z]{1}16.DBF",
}
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
using (ZipFile zip = ZipFile.Read(#"edu.zip"))
{
totalFiles = zip.Count;
filesExtracted = 0;
zip.ExtractProgress += ZipExtractProgress;
zip.ExtractAll(#"./", ExtractExistingFileAction.OverwriteSilently);
}
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
backgroundWorker1.ReportProgress(0);
return;
}
backgroundWorker1.ReportProgress(100);
}
private void ZipExtractProgress(object sender, ExtractProgressEventArgs e)
{
if (e.EventType != ZipProgressEventType.Extracting_BeforeExtractEntry)
return;
filesExtracted++;
this.Dispatcher.Invoke(new Action(() =>
{
progressBar1.Value = 100 * filesExtracted / totalFiles;
}));
}
void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
status.Content = "extractia a fost anulata";
}
else if (e.Error != null)
{
status.Content = "Ceva nu a mers ";
}
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
status.Content = "Se dezarhiveaza......" + progressBar1.Value.ToString() + "%";
}
private void Button_Click(object sender, RoutedEventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
Related
I have a background worker used for running a time consuming sync operation with server and is working perfectly and UI is responsive during the operation
BackgroundWorker syncWorker = new BackgroundWorker();
syncWorker.WorkerReportsProgress = true;
syncWorker.DoWork += new DoWorkEventHandler(syncWorker_DoWork);
syncWorker.ProgressChanged += new ProgressChangedEventHandler(syncWorker_ProgressChanged);
syncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(syncWorker_RunWorkerCompleted);
private void syncWorker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (xxxx item in actives)
{
target.ReportProgress(progress);
//time taking event running fine here..
}
target.ReportProgress(90);
}
private void syncWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
lbl_progress.Text="Wait......";
}
private void syncWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
lbl_progress.Text="DONE!..";
}
Now i have to do a file download operation and i am using Webclient to do it using the code
WebClient downloadClient = new WebClient();
downloadClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(downloadClient_DownloadProgressChanged);
downloadClient.DownloadFileCompleted += new AsyncCompletedEventHandler(downloadClient_DownloadFileCompleted);
downloadClient.DownloadFileAsync(new Uri(fileUrl), download_path);
void downloadClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
int progress_value = int.Parse(Math.Truncate(percentage).ToString());
progress_value = (progress_value < 5) ? 5 : (progress_value > 95) ? 95 : progress_value;
lblDownloadProgress.Content = string.Format("DOWNLOADING - {0}%", progress_value.ToString());
}
void downloadClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
string item = (string)e.UserState;
if (e.Error != null )
{
lblDownloadProgress.Content = "Unable to download.Try again.....";
lblDownloadProgress.Foreground = Brushes.Red;
}
else if (e.Cancelled)
{
//Do Nothing
}
else
{
lblDownloadProgress.Content ="DOWNLOADED..";
}
}
Now can i run these 2 things parallely ? Like run background worker while downlaoding the file??
if file downloading finished first wait till the completion of background worker
if background worker finished first wait till completion of download
Enable controls after both operations finished and keep UI responsive during the whole time
You can run 2 Background worker in parallel but if you need check the state of one of them you can check if the backgroundworker is busy(doing work or completed).
private void syncWorker_DoWork(object sender, DoWorkEventArgs e)
{
while( downloadClient.IsBusy)
{
Sleep(5000);
//waiting downloadClient worker to complete
}
//continue the work
}
look into this for check some trick you can do.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Threading;
namespace download_demo
{
class Program
{
static void Main(string[] args)
{
BackgroundWorker MyWorker = new BackgroundWorker();
MyWorker.DoWork += MyWorker_DoWork;
MyWorker.RunWorkerCompleted +=MyWorker_RunWorkerCompleted;
MyWorker.RunWorkerAsync();
Console.ReadKey();
}
private static void MyWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine("both job completed");
}
private static void MyWorker_DoWork(object sender, DoWorkEventArgs e)
{
Thread download = new Thread(DownloadJob);
download.Start();
for (int i = 0; i < 5; i++)
{
Thread.Sleep(20);
Console.WriteLine("doing some job while downloading ");
}
Console.WriteLine("waiting the end of download......... ");
download.Join();
}
private static void DownloadJob(object path)
{
/// process download the path
///simulate 20 seconde of download
for(int i = 0;i<100;i++)
{
Thread.Sleep(50);
Console.WriteLine("downloaded :" + i + " Ko");
}
}
}
}
So i have been trying over and over with lots of trial and error and i cannot seem to get this to work, basically i want to unzip a zip file using the Ionic.DLL from http://dotnetzip.codeplex.com as you can see i have also made a thread about it here: Extract ZipFile Using C# With Progress Report so to basically sum up what i am after.
I have a form with:
3xbuttons: btnCancel, btnBrowse and btnStart,
1xbackground worker: backgroundworker1
1xlabel: label1
1xtextbox: textBox1
1xprogressbar
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Threading;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Ionic.Zip;
namespace BackgroundWorkerSample
{
public partial class Form1 : Form
{
/// <summary>
/// The backgroundworker object on which the time consuming operation shall be executed
/// </summary>
BackgroundWorker m_oWorker;
public Form1()
{
InitializeComponent();
m_oWorker = new BackgroundWorker();
m_oWorker.DoWork += new DoWorkEventHandler(m_oWorker_DoWork);
m_oWorker.ProgressChanged += new ProgressChangedEventHandler(m_oWorker_ProgressChanged);
m_oWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_oWorker_RunWorkerCompleted);
m_oWorker.WorkerReportsProgress = true;
m_oWorker.WorkerSupportsCancellation = true;
}
/// <summary>
/// On completed do the appropriate task
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void m_oWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//If it was cancelled midway
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
lblStatus.Text = "Task Completed...";
}
btnStartAsyncOperation.Enabled = true;
btnCancel.Enabled = false;
}
/// <summary>
/// Notification is performed here to the progress bar
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void m_oWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Here you play with the main UI thread
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
}
/// <summary>
/// Time consuming operations go here </br>
/// i.e. Database operations,Reporting
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void m_oWorker_DoWork(object sender, DoWorkEventArgs e)
{
//NOTE : Never play with the UI thread here...
//time consuming operation
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
m_oWorker.ReportProgress(i);
/////////////////////MINEEEEEEEEEEEEEEEEEEEEEEEEE
string INSTALL_LOCATION = "C:" + #"\" + "Program Files (x86)" + #"\" + "TEST_FOLDER" + #"\" + #"\" + "Burgos_Folder";
string DEFAULT_LOCATION = "C:" + #"\" + "Program Files (x86)" + #"\" + "TEST_FOLDER" + #"\" + "test.rar";
if (!Directory.Exists(INSTALL_LOCATION))
{
Directory.CreateDirectory(INSTALL_LOCATION);
}
//if the textbox directory exists
if (Directory.Exists(INSTALL_LOCATION))
{
using (ZipFile zip = ZipFile.Read(DEFAULT_LOCATION))
{
zip.ExtractAll(INSTALL_LOCATION, ExtractExistingFileAction.OverwriteSilently);
}
}
//If cancel button was pressed while the execution is in progress
//Change the state from cancellation ---> cancel'ed
if (m_oWorker.CancellationPending)
{
e.Cancel = true;
m_oWorker.ReportProgress(0);
return;
}
}
//Report 100% completion on operation completed
m_oWorker.ReportProgress(100);
}
private void btnStartAsyncOperation_Click(object sender, EventArgs e)
{
btnStartAsyncOperation.Enabled = false;
btnCancel.Enabled = true;
//Start the async operation here
m_oWorker.RunWorkerAsync();
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (m_oWorker.IsBusy)
{
//Stop/Cancel the async operation here
m_oWorker.CancelAsync();
}
}
}
}
What i would like my winforms to have is simply: browse for a folder, then click Start(btnStart) which starts the zip extraction process which is also shown on the ProgressBar(timewise), and the cancel(btnCancel) button cancels the unzipping processs, i have successfully done everything but i cannot work out how to cancel the unzipping process, it never seems to stop unless i actually close the .exe down. I decided to make a simpler example without the textbox and browse button, and that example is in my previous Asked Question(link above), but i don't see how to implement a way to cancel the unzipping process with the background worker, and i definantly need to use background worker so i can have a progress report on the current situation etc. Can anyone please adapt my examples or provide a example that does this?
I have found a solution, i have moved away from Ionic and added the existing references: System.IO.Compression and System.IO.Compression.FileSystem.
I've a background worker that calling a recursive subroutine that traverse a directory, subdirectory and populate the file names into an array. I've a backgroundworker process that is doing this and this also return the percent. I also have a public string dirName that contain the current directory at any given moment and I want it to display together with the percentage (e.g. Processing dirName....nn%), how do I do that?
void m_bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pictureBox1.Visible = true;
pictureBox1.Refresh();
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing + dirName + "....." + progressBar1.Value.ToString() + "%";
}
void m_bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
if (m_bgWorker.CancellationPending)
{
e.Cancel = true;
m_bgWorker.ReportProgress(0);
return;
}
else
{
//e.Result containing an array of directories
e.Result = processFile(pgmName, pgmPath, worker, e);
}
m_bgWorker.ReportProgress(100);
}
In your processFile() method, you'd report progress and pass back the directory using the overload of ReportProgress() that takes an object:
int progress = 0;
string directory = "C:\Foo\Bazz";
while(...)
{
//...
//...
m_bgWorker.ReportProgress(progress, directory);
}
Then in your m_bgWorker_ProgressChanged(), you'd do this to get the directory out:
void m_bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pictureBox1.Visible = true;
pictureBox1.Refresh();
progressBar1.Value = e.ProgressPercentage;
string dirName = e.UserState.ToString();
lblStatus.Text = "Processing" + dirName + "....." + progressBar1.Value.ToString() + "%";
}
A great resource for learning more about BackgroundWorker is Joseph Albahari's page on the class, which is a part of a larger article on threading in C#.
In the top of the form i did:
progressBar1.Maximum = 100;
progressBar1.Minimum = 1;
Then in the button click event that start the operation i did:
timer2.Enabled = true;
if (this.backgroundWorker1.IsBusy == false)
{
this.backgroundWorker1.RunWorkerAsync();
}
Then in the backgroundworkerdowork event:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if (filesContent.Length > 0)
{
for (int i = 0; i < filesContent.Length; i++)
{
File.Copy(filesContent[i], Path.Combine(contentDirectory, Path.GetFileName(filesContent[i])), true);
}
}
DoProgressBar(e, worker);
WindowsUpdate();
CreateDriversList();
GetHostsFile();
Processes();
}
All the functions in the DoWork event are copying files the Processes() function use a new class i did that use Process to create/copy files.
Then the new DoProgressBar event function i did:
private static void DoProgressBar(DoWorkEventArgs e, BackgroundWorker worker)
{
for (int i = 1; i <= 90; i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(50);
worker.ReportProgress(i);
}
}
}
Then ProgressChanged event:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
Then the completed event:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
this.label1.Text = "Canceled!";
}
else if (!(e.Error == null))
{
this.label1.Text = ("Error: " + e.Error.Message);
}
else
{
this.progressBar1.Value = this.progressBar1.Maximum;
processfinish = true;
}
}
Timer2 tick event:
private void timer2_Tick(object sender, EventArgs e)
{
timerCount += 1;
TimerCount.Text = TimeSpan.FromSeconds(timerCount).ToString();
TimerCount.Visible = true;
if (processfinish == true)
{
timer2.Enabled = false;
timer1.Enabled = true;
}
}
And timer1 tick event:
private void timer1_Tick(object sender, EventArgs e)
{
count++;
Diagnose.Text = "PROCESS HAS FINISHED" + " " + countBack--;
if (count == 6)
{
Diagnose.Text = "COLLECT INFORMATION";
Diagnose.Enabled = true;
CreateZip.Enabled = true;
ViewLogFile.Enabled = true;
DriverVerifier.Enabled = true;
timer1.Enabled = false;
TimerCount.Visible = false;
}
}
I know its a long code but everything here is connected.
What i wanted to do is that the progressBar will get progress according to the progress of each function in the DoWork event .
But instead what is it doing now is first going to the :
DoProgressBar() event/function do the second/else part ReportProgress(i)
Then its going to the Progresschanged event and do: progressBar1.Value = e.ProgressPercentage;
The result is when i click the button click to start the opertion i see right away the progress bar moving almost to the end instead moving according to each function/progress of the program.
You can see my complete code of Form1 here:
http://codepaste.net/fuk9w5
EDIT:
This is the code of the class ProcessRun where im using in Form1 in the function Processes()
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
namespace Diagnostic_Tool_Blue_Screen
{
class ProcessRun
{
public void ProcessesRun()
{
}
public static void Processing(string WorkingDirectory, string FileName, string Arguments, bool StandardOutput, string OutputFileName)
{
Process proc = new Process();
proc.EnableRaisingEvents = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = StandardOutput;
proc.StartInfo.FileName = FileName;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.WorkingDirectory = WorkingDirectory;
proc.StartInfo.Arguments = Arguments;
proc.Start();
if (StandardOutput == true)
{
string output = proc.StandardOutput.ReadToEnd();
DumpOutput(WorkingDirectory + "\\" + OutputFileName, output);
}
proc.WaitForExit();
proc.Close();
}
private static void DumpOutput(string filename, string output)
{
StreamWriter w = new StreamWriter(filename);
w.Write(output);
w.Close();
}
}
}
It appears that your background thread is interacting directly with a UI element (the progress bar). That's a problem. Your background thread can't directly interact with the UI element; it has to invoke it such that the UI update occurs on the UI thread.
You could, for example, add a method like this to your form:
// Form method for updating progress bar; callable from worker thread
public void UpdateProgressBar(double progress)
{
// dispatch the update onto the form's thread
Dispatcher.BeginInvoke((Action<double>)((n) =>
{
// do the update in the form's thread
progressBar1.Value = n;
}), progress);
}
You can then call this method from your worker thread and the progress bar should update properly.
why not put this into your code? This is how I move the "green" part of the progressbar.
progressBar1.Step = pos; //where pos is the number on how much do you want to increase the progress of the progressbar
progressBar1.PerformStep(); //triggers the movement of the progressBar.
For those who ended up here while trying to find a way to change value of progess bar with cross threading this is how you do it:
form.Invoke((Action)delegate { form.function(); });
When I cancel and dispose of my background worker, despite it disappearing from the VS threads list it continues to report busy to my application which is waiting for it to close. Also my RunWorkerCompleted event is never raised.
Debugging shows that the code is exited with no further pending execution that I can see.
If I remove the .IsBusy check, VS reports that "This BackgroundWorker is currently busy and cannot run multiple tasks concurrently"
I cannot understand why the thread which is no longer listed in VS continues to operate after closing.
private void UpdateTimeLine()
{
txtb_timeline.Text = "Updating...";
startTimelineUpdater.DoWork += new DoWorkEventHandler(startTimelineUpdater_DoWork);
startTimelineUpdater.RunWorkerAsync("hometimeline");
startTimelineUpdater.WorkerReportsProgress = true;
startTimelineUpdater.ProgressChanged += new ProgressChangedEventHandler
(startTimelineUpdater_ProgressChanged);
startTimelineUpdater.WorkerSupportsCancellation = true;
}
void startTimelineUpdater_DoWork(object sender, DoWorkEventArgs e)
{
//begin the thread to maintain updates of SQL
beginRegUpdateTimeline.DoWork += new DoWorkEventHandler(beginRegUpdateTimeline_DoWork);
beginRegUpdateTimeline.RunWorkerAsync();
beginRegUpdateTimeline.WorkerSupportsCancellation = true;
while (true)
{
List<string[]> sqlset;
Xtweet getSQL = new Xtweet();
if(e.Argument.ToString() == "hometimeline")
{
sqlset = getSQL.CollectLocalTimelineSql();
}
else
{
sqlset = getSQL.CollectLocalTimelineSql(Int64.Parse(e.Argument.ToString()));
}
int i = 0;
while (i < 10)
{
foreach (var stringse in sqlset)
{
StringBuilder sb = new StringBuilder();
sb.Append(stringse[0]);
sb.Append(": ");
sb.Append(stringse[1]);
sb.Append(" # ");
sb.Append(stringse[2]);
sb.Append("\n");
BackgroundWorker bkgwk = sender as BackgroundWorker;
bkgwk.ReportProgress(0, sb.ToString());
Thread.Sleep(1000);
i++;
if(startTimelineUpdater.CancellationPending)
{
e.Cancel = true;
startTimelineUpdater.Dispose();
break;
}
}
if (e.Cancel == true)
{
break;
}
}
if (e.Cancel == true)
{
break;
}
}
}
/// <summary>
/// Handles the DoWork event of the beginRegUpdateTimeline control.
/// Updates the timeline sql on a regular basis
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
void beginRegUpdateTimeline_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
//update time in seconds
int secs = 10;
Xtweet.PreSqlDataCollection(null,null);
Thread.Sleep(secs*1000);
if(beginRegUpdateTimeline.CancellationPending)
{
e.Cancel = true;
beginRegUpdateTimeline.Dispose();
break;
}
}
}
private void startTimelineUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
txtb_timeline.Text = e.UserState.ToString();
}
Call Application.DoEvents after thread sleep.
As mentioned here:
the BackgroundWorker simply does not report it is done until the UI
thread gets control.
Update:
Since this is WPF, you should be using Dispatcher