The intention is to make a progress bar move according to the compression of files, but it only works in the decompression (not showed on code), where is the problem?
private void Compress(string source)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
progressBar1.Value = 0;
progressBar1.Visible = true;
var progressHandled =
new Progress<byte>(percentDone => progressBar1.Value = percentDone);
var progress = progressHandled as IProgress<byte>;
Task.Run(() =>
{
string SZpath = Directory.GetCurrentDirectory() + #"\64-7z.dll";
SevenZipBase.SetLibraryPath(SZpath);
SevenZipCompressor compressor = new SevenZipCompressor();
compressor.ArchiveFormat = OutArchiveFormat.Zip;
compressor.TempFolderPath = Path.GetTempPath();
compressor.CompressionMode = SevenZip.CompressionMode.Create;
compressor.CompressionLevel = SevenZip.CompressionLevel.Fast;
compressor.CompressionMethod = CompressionMethod.Lzma;
compressor.ZipEncryptionMethod = ZipEncryptionMethod.Aes256;
compressor.Compressing += (sender, args) =>
{
progress.Report(args.PercentDone);
};
compressor.CompressionFinished += (sender, args) =>
{
};
compressor.CompressDirectory(source, #"A:\C#\empty\archive.zip", "password");
});
log("Ended"); // the void is not on code
}
The code works perfectly, the problem is that the progressbar never moved
Thank you for your time, I look forward to your answer.
Related
using System;
using System.ComponentModel;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Net;
namespace Seranking_Scraper
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
btnStop.Enabled = false;
}
CancellationTokenSource cts = null;
List<string> proxyList = new List<string>();
int _proxyIndex = 0;
int retries = 0;
int linesCount = 1;
int totalLinesCount;
List<Task> tasks = null;
string regex = "XXXXXX";
private static HttpClient client = null;
private async void BtnStart_Click(object sender, EventArgs e)
{
dataGridView1.Rows.Clear();
cts = new CancellationTokenSource();
btnStart.Enabled = false;
btnStop.Enabled = true;
btnExport.Enabled = false;
btnOpen.Enabled = false;
btnClear.Enabled = false;
totalLinesCount = listBox_domains.Items.Count;
List<string> urls = new List<string>();
for (int i = 0; i < listBox_domains.Items.Count; i++)
{
urls.Add(listBox_domains.Items[i].ToString());
}
if (textBox_Proxies.Text != null)
{
for (int i = 0; i < textBox_Proxies.Lines.Length; i++)
{
proxyList.Add(textBox_Proxies.Lines[i]);
}
}
var maxThreads = (int)numericUpDown1.Value;
var q = new ConcurrentQueue<string>(urls);
tasks = new List<Task>();
for (int n = 0; n < maxThreads; n++)
{
tasks.Add(Task.Run(async () =>
{
while (q.TryDequeue(out string url))
{
await SendHttpRequestAsync(url, cts.Token);
Thread.Sleep(1);
if (cts.IsCancellationRequested)
{
break;
}
foreach (Task eTask in tasks)
{
if (eTask.IsCompleted)
eTask.Dispose();
}
}
}, cts.Token));
}
await Task.WhenAll(tasks).ContinueWith((FinalWork) =>
{
Invoke(new Action(() =>
{
btnStart.Enabled = true;
btnExport.Enabled = true;
btnOpen.Enabled = true;
btnClear.Enabled = true;
timer1.Enabled = false;
timer1.Stop();
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Invoke((Action)(() => progressBar1.Value = 100));
if(!cts.IsCancellationRequested)
MessageBox.Show(new Form { TopMost = true }, "Completed!", "Status", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}));
}, TaskContinuationOptions.OnlyOnRanToCompletion);
//var options = new ParallelOptions()
//{
// MaxDegreeOfParallelism = (int)numericUpDown1.Value
//};
//Parallel.For(0, listBox_domains.Items.Count, async j =>
//{
// await SendHttpRequestAsync(listBox_domains.Items[j].ToString());
// Thread.Sleep(10);
//});
}
private string GetProxy()
{
if (proxyList.Count <=0) return null;
if (_proxyIndex >= proxyList.Count - 1) _proxyIndex = 0;
var proxy = proxyList[_proxyIndex];
_proxyIndex++;
return proxy;
}
private async Task ToCsV(DataGridView dGV, string filename)
{
await Task.Yield();
string stOutput = "";
// Export titles:
string sHeaders = "";
for (int j = 0; j < dGV.Columns.Count; j++)
sHeaders = sHeaders.ToString() + Convert.ToString(dGV.Columns[j].HeaderText) + "\t";
stOutput += sHeaders + "\r\n";
// Export data.
for (int i = 0; i < dGV.RowCount - 1; i++)
{
string stLine = "";
for (int j = 0; j < dGV.Rows[i].Cells.Count; j++)
stLine = stLine.ToString() + Convert.ToString(dGV.Rows[i].Cells[j].Value) + "\t";
stOutput += stLine + "\r\n";
//progressBar1.Style = ProgressBarStyle.Blocks;
//progressBar1.Value = (i / 100) * 100;
}
Encoding utf16 = Encoding.GetEncoding(1254);
byte[] output = utf16.GetBytes(stOutput);
FileStream fs = new FileStream(filename, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(output, 0, output.Length); //write the encoded file
bw.Flush();
bw.Close();
fs.Close();
}
private async Task SendHttpRequestAsync(string url, CancellationToken ct)
{
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy(GetProxy(), false),
UseProxy = true
};
//httpClientHandler.MaxConnectionsPerServer = 1;
httpClientHandler.AllowAutoRedirect = true;
httpClientHandler.MaxAutomaticRedirections = 3;
try
{
using (client = new HttpClient(httpClientHandler))
{
client.Timeout = TimeSpan.FromMilliseconds(1000 * (int)numericUpDown_timeout.Value); //adjust based on your network
client.DefaultRequestHeaders.ConnectionClose = true;
ServicePointManager.DefaultConnectionLimit = 100;
//var byteArray = Encoding.ASCII.GetBytes("username:password1234");
//client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
try
{
using (HttpResponseMessage response = await client.GetAsync("xxxx))
{
if (response.IsSuccessStatusCode)
{
using (HttpContent content = response.Content)
{
//response.Dispose();
string result = await content.ReadAsStringAsync();
Regex match = new Regex(regex, RegexOptions.Singleline);
MatchCollection collection = Regex.Matches(result, regex);
try
{
if (collection.Count > 0)
{
await AddDataToDgv(url, collection[0].ToString(), collection[1].ToString(), collection[2].ToString());
}
else if (result.Contains("No data for your search query"))
{
await AddDataToDgv(url, "nodata", "nodata", "nodata");
}
}
catch (Exception ex)
{
//MessageBox.Show(ex.ToString());
await AddDataToDgv(url, "errorCount", "errorCount", "errorCount");
}
}
}
else
{
await RetriesProxyFail(url, ct);
}
}
}catch(Exception ex)
{
await RetriesProxyFail(url, ct, ex);
client.Dispose();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
public async Task RetriesProxyFail(string url, CancellationToken ct, Exception ex = null)
{
client.DefaultRequestHeaders.ConnectionClose = true;
if (!cts.IsCancellationRequested)
{
retries++;
if (retries > (int)numericUpDown_Retries.Value)
{
retries = 0;
Invoke(new Action(async () =>
{
lbl_RemainingLines.Text = "Remaining Urls: " + (totalLinesCount - (dataGridView1.Rows.Count)).ToString();
await AddDataToDgv(url, "timeout", "timeout", "timeout");
}));
}
else
{
await SendHttpRequestAsync(url, ct);
}
}
}
public async Task AddDataToDgv(string url, string tcost, string tTraffic, string tValue)
{
try
{
await Task.Yield();
Invoke(new Action(() =>
{
dataGridView1.Rows.Add(url, tcost, tTraffic, tValue);
lbl_RemainingLines.Text = "Remaining Urls: " + (totalLinesCount - (dataGridView1.Rows.Count)).ToString();
if (Application.RenderWithVisualStyles)
progressBar1.Style = ProgressBarStyle.Marquee;
else
{
progressBar1.Style = ProgressBarStyle.Continuous;
progressBar1.Maximum = 100;
progressBar1.Value = 0;
timer1.Enabled = true;
}
}));
}
catch (Exception ex)
{
Invoke(new Action(async () =>
{
lbl_RemainingLines.Text = "Remaining Urls: " + (totalLinesCount - (dataGridView1.Rows.Count)).ToString();
await AddDataToDgv(url, "error", "error", "error");
}));
}
}
private void BtnOpen_Click(object sender, EventArgs e)
{
linesCount = 1;
try
{
openFileDialog1.ShowDialog();
openFileDialog1.Title = "Please select text file that contains root domains.";
openFileDialog1.DefaultExt = "txt";
openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog1.FilterIndex = 2;
openFileDialog1.CheckFileExists = true;
openFileDialog1.CheckPathExists = true;
this.openFileDialog1.Multiselect = true;
myWorker_ReadTxtFile = new BackgroundWorker();
myWorker_ReadTxtFile.DoWork += new DoWorkEventHandler(MyWorker_ReadTxtFile_DoWork);
myWorker_ReadTxtFile.RunWorkerCompleted += new RunWorkerCompletedEventHandler(MyWorker_ReadTxtFile_RunWorkerCompleted);
myWorker_ReadTxtFile.ProgressChanged += new ProgressChangedEventHandler(MyWorker_ReadTxtFile_ProgressChanged);
myWorker_ReadTxtFile.WorkerReportsProgress = true;
myWorker_ReadTxtFile.WorkerSupportsCancellation = true;
listBox_domains.Items.Clear();
foreach (String fileName_Domains in openFileDialog1.FileNames)
{
myWorker_ReadTxtFile.RunWorkerAsync(fileName_Domains);
}
}
catch (Exception ex)
{
}
}
private void OpenFileDialog1_FileOk(object sender, CancelEventArgs e)
{
}
private void MyWorker_ReadTxtFile_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
listBox_domains.Items.Add(e.UserState.ToString());
lbl_totallines.Text = "TLines: " + linesCount++.ToString();
}
private void MyWorker_ReadTxtFile_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
public void ReadLinesToListBox(string fileName_Domains)
{
using (StreamReader sr = File.OpenText(fileName_Domains))
{
string s = String.Empty;
while ((s = sr.ReadLine()) != null)
{
myWorker_ReadTxtFile.ReportProgress(0, s);
Thread.Sleep(1);
}
}
}
private void MyWorker_ReadTxtFile_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker sendingWorker = (BackgroundWorker)sender;//Capture the BackgroundWorker that fired the event
object fileName_Domains = (object)e.Argument;//Collect the array of objects the we received from the main thread
string s = fileName_Domains.ToString();//Get the string value
ReadLinesToListBox(s);
}
private void Label2_Click(object sender, EventArgs e)
{
}
private void BtnStop_Click(object sender, EventArgs e)
{
if (cts != null)
{
cts.Cancel();
cts.Dispose();
btnStart.Enabled = true;
btnStop.Enabled = false;
btnExport.Enabled = true;
btnOpen.Enabled = true;
btnClear.Enabled = true;
progressBar1.Style = ProgressBarStyle.Blocks;
progressBar1.Value = 100;
MessageBox.Show(new Form { TopMost = true }, "Cancelled!", "Status", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
private async void BtnExport_Click(object sender, EventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Excel Documents (*.xls)|*.xls";
sfd.FileName = "Site Metrics";
if (sfd.ShowDialog() == DialogResult.OK)
{
await ToCsV(dataGridView1, sfd.FileName); // Here dataGridview1 is your grid view name
}
MessageBox.Show(new Form { TopMost = true }, "Exported!", "Status", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
private void BtnClear_Click(object sender, EventArgs e)
{
listBox_domains.Items.Clear();
dataGridView1.Rows.Clear();
}
private void Form1_Load(object sender, EventArgs e)
{
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
}
private void BtnPasteProxies_Click(object sender, EventArgs e)
{
textBox_Proxies.Text = Clipboard.GetText();
}
private void Timer1_Tick(object sender, EventArgs e)
{
progressBar1.Value += 5;
if (progressBar1.Value > 100)
progressBar1.Value = 0;
}
}
}
The above code is working fine but the problem is it slowly increasing the memory usage. When I start it use some around 40 mb slowly its increasing I tried memory tests, the increase in memory is slow but its increasing slowly.
Any one help me whats wrong in my code?
I am testing with some 4k urls, when it reaches 2k urls my memory usage is 60 MB. Still increasing slowly.
A slow memory increase is totally normal. .NET uses Garbage Collection Memory Management approach. Now while the collection runs, every other thread has to stop. This can cause human noticeable stalls. And is one big reason GC and realtime programming do not mix that well.
To avoid those stalls, the GC is lazy with running. It is aiming for only running once - at application closure. Delays will not be that noticeable then. And it might even be able to save work, as the memory will be handed back to the OS afterwards and not be reused. Short of running finalizers, there might not be much work to be done.
There are only a few things that can force it to run earlier:
there is a danger of a OutOfMemory exception. The GC will have collected and defragmented everything it possibly could before you ever get that Exception.
you call GC.Collect(); It allows you to force a collection now. Note that this only adviseable for debugging and testing. Production code should not have this
you pick a GC strategy that differs from Desktop applciation default. There are ones that do the reachabiltiy checks in anotehr thread, to have that work not pause all threads. Ones that run regulary but avoid defragmentation. Even ones that run regulary with a upper bound on runtime (to limit the stalls).
I'm trying to update the progress bar of my windows forms application,which is basically an application to download youtube videos. However I get an exception called 'System.ArgumentOutOfRangeException' on the progressbar method. Please help me solve this. Thanks! :)
private void button1_Click(object sender, EventArgs e)
{
progressBarOverall.Minimum = 0;
progressBarOverall.Minimum = 100;
IEnumerable<VideoInfo> videos = DownloadUrlResolver.GetDownloadUrls(textBox1.Text);
VideoInfo video = videos.First(p => p.VideoType == VideoType.Mp4 && p.Resolution == Convert.ToInt32(cboResolution.Text));//converts video quality
if(video.RequiresDecryption) //Checks if video requiures decryption before downloading the URL
DownloadUrlResolver.DecryptDownloadUrl(video);//
VideoDownloader downloader = new VideoDownloader(video, Path.Combine(Application.StartupPath + "//", video.Title + video.VideoExtension));
downloader.DownloadProgressChanged += Downloader_DownloadProgressChanged;
Thread thread = new Thread(() => { downloader.Execute(); }) { IsBackground = true };
thread.Start();
}
private void Downloader_DownloadProgressChanged(object sender, ProgressEventArgs e)
{
Invoke(new MethodInvoker(delegate ()
{
progressBarOverall.Value = (int)e.ProgressPercentage;
percentagelabel.Text = $"{string.Format("{0:0.##}", e.ProgressPercentage)}%";
progressBarOverall.Update();
}));
}
progressBarOverall.Minimum = 0;
progressBarOverall.Minimum = 100;
You mean maximum for the second one?
progressBarOverall.Minimum = 0;
progressBarOverall.Maximum= 100;
I'm creating a backup application. I have 5 folders in different locations what needs to be copied to one backup folder. (solved via checkbox.checked)
The main issue is that some of the folders are more than 3-4GB in total (with all subfolders) Progressbar is not updated because "maxbyte" returns a negative value. (I assume int32 overflows after 2gb file copy)
(Sorry can't explain it more in details..I'm just a beginner C# programmer)
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using memoQClientBackuTool;
namespace memoQBackupTool
{
public partial class BGWorker : Form
{
public BGWorker()
{
InitializeComponent();
}
BackgroundWorker bw;
string source = "";
string target = "";
bool isfile = false;
int filecount = 0;
int currentFileNr = 1;
string newFilename = "";
int maxbytes = 0;
public void ShowProgress(string from, string to, bool isf)
{
InitializeComponent();
source = from;
target = to;
isfile = isf;
bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.WorkerReportsProgress = true;
bw.WorkerSupportsCancellation = true;
GetFileData();
}
private void GetFileData()
{
if (isfile)
{
FileInfo fi = new FileInfo(source);
maxbytes = Convert.ToInt32(fi.Length);
//
//set progress bar length
//
progressBar1.Minimum = 0;
progressBar2.Minimum = 0;
progressBar1.Maximum = maxbytes;
progressBar2.Maximum = 1;
bw.RunWorkerAsync();
}
else
{
GetDirectoryInfo(source);
//
//set progress bar length
//
progressBar1.Minimum = 0;
progressBar2.Minimum = 0;
progressBar1.Maximum = maxbytes;
progressBar2.Maximum = filecount;
bw.RunWorkerAsync();
}
}
private void GetDirectoryInfo(string source)
{
string[] files = Directory.GetFiles(source);
foreach (string file in files)
{
FileInfo fi = new FileInfo(file);
maxbytes += Convert.ToInt32(fi.Length);
filecount += 1;
}
string[] folders = Directory.GetDirectories(source);
foreach (string folder in folders)
{
GetDirectoryInfo(folder);
}
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
if (isfile)
{
FileStream fs = new FileStream(source, FileMode.Open);
long FileSize = fs.Length;
FileInfo fi = new FileInfo(source);
byte[] bBuffer = new byte[(int)FileSize];
fs.Read(bBuffer, 0, (int)FileSize);
fs.Close();
UpdateLabels(fi.FullName);
newFilename = fi.Name;
try
{
FileStream fss = new FileStream(target + "\\" + newFilename, FileMode.CreateNew);
BinaryWriter biwr = new BinaryWriter(fss);
for (int i = 0; i < bBuffer.Length; i += 15000)
{
if (i + 15000 < bBuffer.Length)
{
biwr.Write(bBuffer, i, 15000);
bw.ReportProgress(15000);
}
else
{
biwr.Write(bBuffer, i, bBuffer.Length - i);
bw.ReportProgress(bBuffer.Length - i);
}
}
biwr.Close();
fss.Close();
} catch (IOException){
MessageBox.Show("Nincs olyan...");
}
}
else
{
string[] temp = source.Split('\\');
target += "\\" + temp[temp.Count() - 1];
DirectoryInfo s = new DirectoryInfo(source);
DirectoryInfo t = new DirectoryInfo(target);
CopyDirectory(s, t);
}
if (bw.CancellationPending)
{
e.Cancel = true;
return;
}
}
public void CopyDirectory(DirectoryInfo di_source, DirectoryInfo di_target)
{
if (Directory.Exists(di_target.FullName) == false)
{
Directory.CreateDirectory(di_target.FullName);
}
foreach (FileInfo fi in di_source.GetFiles())
{
newFilename = fi.Name;
FileStream fs = new FileStream(fi.FullName, FileMode.Open);
long FileSize = fs.Length;
byte[] bBuffer = new byte[(int)FileSize];
fs.Read(bBuffer, 0, (int)FileSize);
fs.Close();
UpdateLabels(fi.FullName);
if (File.Exists(di_target.ToString() + "\\" + fi.Name))
{
Random rand = new Random();
newFilename = newFilename + "_" + rand.Next(1, 10000);
}
FileStream fss = new FileStream(di_target.ToString() + "\\" + newFilename, FileMode.CreateNew);
BinaryWriter biwr = new BinaryWriter(fss);
for (int i = 0; i < bBuffer.Length; i += 500000)
{
if (i + 500000 < bBuffer.Length)
{
biwr.Write(bBuffer, i, 500000);
bw.ReportProgress(500000);
}
else
{
biwr.Write(bBuffer, i, bBuffer.Length - i);
bw.ReportProgress(bBuffer.Length - i);
}
}
biwr.Close();
fss.Close();
}
foreach (DirectoryInfo di_SourceSubDir in di_source.GetDirectories())
{
DirectoryInfo nextSubDir = di_target.CreateSubdirectory(di_SourceSubDir.Name);
CopyDirectory(di_SourceSubDir, nextSubDir);
}
}
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value += e.ProgressPercentage;
int copied = progressBar1.Value / 1024;
int total = maxbytes / 1024;
lbl_kbscopied.Text = copied + "/" + total;
}
delegate void UpdateLabelsDelegate(string filename);
void UpdateLabels(string fname)
{
if (!InvokeRequired)
{
lbl_filename.Text = "Copying: " + fname;
lbl_filenr.Text = "File: " + currentFileNr + "/" + filecount;
currentFileNr++;
progressBar2.Value += 1;
}
else
{
Invoke(new UpdateLabelsDelegate(UpdateLabels), new object[] { fname });
}
}
private void button1_Click(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
bw.CancelAsync();
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
Cursor.Current = Cursors.Default;
CustomMsgBox.Show("The task has been canceled", "Error", "OK");
this.Close();
}
else if (e.Error != null)
{
MessageBox.Show("Error. Details: " + (e.Error as Exception).ToString());
}
else
{
this.Close();
}
}
}
}
Report progress not in absolute values, but in relative; percentage, for example.
Let say that 1MB file is 100% of progress bar. That means that you have to initialize it with 100: progressBar1.Maximum = 100. Then every 15000 bytes that were copied is a little bit more than 1%. Instead of bw.ReportProgress(15000) do bw.ReportProgress(1).
I will suggest to use long instead of int wherever you are getting total bytes copied/uploaded so far. If I understood your code you are using int in for loop where you call ReportProgress
I have a ListBox which I put some files, if the file is not AVI I automatically converts it but I want when the files converting message will write on a label that the files are now converted to another format, what happens to me now is only when the program has finished converting them its update the label and not in the process
after all the fixes:
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
btnPlay.IsEnabled = false;
Stream checkStream = null;
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
openFileDialog.Multiselect = true;
openFileDialog.InitialDirectory = "c:\\";
openFileDialog.Filter = "All files (*.*)|*.*";
openFileDialog.FilterIndex = 1;
openFileDialog.Title = "Please Select Source File";
if ((bool)openFileDialog.ShowDialog())
{
if ((checkStream = openFileDialog.OpenFile()) != null)
{
foreach (string file in openFileDialog.FileNames)
{
try
{
FileInfo fileInfo = new FileInfo(file);
listBoxFiles.Items.Add(file);
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
for (int i = 0; i < listBoxFiles.Items.Count; i++)
{
string path = (string)listBoxFiles.Items[i];
FileInfo fileInfo = new FileInfo(path);
if (fileInfo.Extension != ".AVI")
{
listToRemove.Add(path);
}
}
(new System.Threading.Thread(ProcessAviFiles)).Start();
foreach (string file in listToRemove) //remove all non .AVI files from listbox
{
listBoxFiles.Items.Remove(file);
}
}
}
else
{
}
if (listBoxFiles.Items.Count != 0)
{
btnClear.IsEnabled = true;
btnPlay.IsEnabled = true;
}
listToRemove.RemoveRange(0, listToRemove.Count);
}
function:
public void ProcessAviFiles()
{
if (listToRemove.Count == 0)
{
return;
}
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() => { lblStatus2.Content = "Convert file to .AVI..."; }));
foreach (String file in listToRemove)
{
FileInfo fileInfo = new FileInfo(file);
editpcap = new EditCap(fileInfo);
String newFileName = editpcap._newFileName;
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
{
listBoxFiles.Items.Add(editpcap._newFileName);
}));
}
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
() =>
{
lblStatus2.Content = "Select adapter and packet file, Click play button to start.";
btnClear.IsEnabled = true;
}));
}
The label is not updating because the main UI thread is busy doing other things.
Looking to your code, it seems that you are running the AVI file conversion business inside your main UI thread. You should run this time consuming task in a separate thread to make sure your UI stays responsive.
Below is a fix to your problem, replace your foreach (String file in listToRemove){} by:
Action aviConversion = new Action(() => {
if(listToRemove.Count == 0) return; // nothing to do
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => { lblStatus2.Content = "Convert file to .AVI...";});
);
foreach (String file in listToRemove){
FileInfo fileInfo = new FileInfo(file);
editpcap = new (classes who convert the files)(fileInfo);
String newFileName = editpcap._newFileName;
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => {
listBoxFiles.Items.Add(newFileName);
}));
}
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => { lblStatus2.Content = "AVI file conversion finished...";});
});
// Run this action in a separate thread...
Task.Factory.StartNew(action, "beta");
EDIT Using Thread instead of Task (OP can't use Task)
private void ProcessAviFiles(){
if(listToRemove.Count == 0) return; // nothing to do
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => { lblStatus2.Content = "Convert file to .AVI...";});
);
foreach (String file in listToRemove){
FileInfo fileInfo = new FileInfo(file);
editpcap = new (classes who convert the files)(fileInfo);
String newFileName = editpcap._newFileName;
Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => {
listBoxFiles.Items.Add(newFileName);
}));
}
lblStatus2.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(() => { lblStatus2.Content = "AVI file conversion finished...";});
}
replace your foreach (String file in listToRemove){} by:
(new System.Threading.Thread(ProcessAviFiles)).Start();
Use BackgroundWorker for the main task and dispatcher for UI updates.
backgroundWorker1.DoWork += worker_DoWork;
backgroundWorker1.RunWorkerCompleted += worker_RunWorkerCompleted;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.ProgressChanged +=new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
I have a collection of picture Objects for which I need to download thumbs and pictures files located on dataservise, how can I managed this?
In this method I have loop to call three methods; one to add objects to data base, second to download and save picture thumb and third to download and save picture file the other two is ClientOpenReadCompleted methods.
public bool AddAllPhoto()
{
var amount = App.ViewModel.NewPictures.Count;
for (int i = 0; i < amount; i++)
{
//to add picture to DB
SavePicture(App.ViewModel.NewPictures[i]);
DownloadPicture(NewPictures[i].ID.ToString());
DownloadPictureThumb(NewPictures[i].ID.ToString()));
}
return true;
}
Second;
public void DownloadPictureThumb(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/ /Pictures/Thumbs/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted1;
client.OpenReadAsync(new Uri(outputString));
}
private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
var thumbFilePath = String.Format(PicturesThumbsColectionKey + "{0}", PictureDataStoreLocal.ID);
var stream = thumbFile.CreateFile(thumbFilePath);
stream.Write(contents, 0, contents.Length);
stream.Close();
}
And third one
public void DownloadPicture(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted1;
client.OpenReadAsync(new Uri(outputString));
}
private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream stream = file.CreateFile(PictureDataStoreLocal.ID.ToString());
stream.Write(contents, 0, contents.Length);
stream.Close();
}
I assume you want to process the pictures synchronously. If so I would use a wait handle. The easiest way to do this would be to declare a private AutoResetEvent field. The AutoResetEvent is good here because it just lets one thread through and then blocks again automatically.
If you do this you will need to make sure of two things:
1. You do ALL work on a different thread so that when you call WaitOne() you aren't blocking the thread that is supposed to be doing the work.
2. You always reset the wait handle regardless of the outcome of the server calls.
To take care of 1. you just need to update your loop:
m_waitHandle.Reset(); // Make sure the wait handle blocks when WaitOne() is called
for (int i = 0; i < amount; i++)
{
// Process on a background thread
ThreadPool.QueueUserWorkItem((obj) =>
{
// Get the current index. This is an anonymous method so if
// we use 'i' directly we will not necessarily be using the
// correct index. In our case the wait handle avoids this
// problem as the pictures are downloaded one after the other
// but it's still good practise to NEVER use a loop variable in
// an anonymous method.
int index = (int)obj;
//to add picture to DB
SavePicture(App.ViewModel.NewPictures[index]);
DownloadPicture(NewPictures[index].ID.ToString());
DownloadPictureThumb(NewPictures[index].ID.ToString()));
}, i);
m_waitHandle.WaitOne(); // Wait for processing to finish
}
For 2. you need to make sure that m_waitHandle.Set() is ALWAYS called when processing is finished.
What I do is send extra parameters to the OpenReadCompleted event using a delegate like so,
someimage.LoadingCompleted += delegate(object sender, EventArgs imge) { someimage_LoadingCompleted(sender, imge, _item, "someimage"); };
and then in someimage_LoadingCompleted I have code within a switch statement.
Here is my solution, not that elegant but working one; If you have any suggestion to improve , please post and I will edit my post.
EventWaitHandle m_WaitHandle;
public bool AddAllPhoto()
{
var amount = App.ViewModel.NewPictures.Count;
if (m_WaitHandle!=null)
m_WaitHandle.Reset();
for (int i = 0; i < amount; i++)
{
{
SavePicture(App.ViewModel.NewPictures[i]);
ThreadPool.QueueUserWorkItem((obj) =>
{
var index = (int)obj;
DownloadPictureThumb(App.ViewModel.NewPictures[index].ID.ToString());
DownloadPicture(App.ViewModel.NewPictures[index].ID.ToString());
},i);
if (m_WaitHandle != null) m_WaitHandle.WaitOne();
}
return true;
}
public void DownloadPictureThumb(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/Thumbs/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted2;
client.OpenReadAsync(new Uri(outputString),path);
}
private static void ClientOpenReadCompleted2(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
var thumbFilePath = String.Format(PicturesThumbsColectionKey + "{0}", e.UserState as string);
var stream = file.CreateFile(thumbFilePath);
stream.Write(contents, 0, contents.Length);
stream.Close();
}
public void DownloadPicture(string path)
{
string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/{0}.jpg", path);
var client = new WebClient();
client.OpenReadCompleted += ClientOpenReadCompleted1;
client.OpenReadAsync(new Uri(outputString), path);
}
private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
{
var resInfo = new StreamResourceInfo(e.Result, null);
var reader = new StreamReader(resInfo.Stream);
byte[] contents;
using (var bReader = new BinaryReader(reader.BaseStream))
{
contents = bReader.ReadBytes((int)reader.BaseStream.Length);
}
var file = IsolatedStorageFile.GetUserStoreForApplication();
var stream = file.CreateFile(e.UserState as string);
stream.Write(contents, 0, contents.Length);
stream.Close();
}
[Here][1] you will find explanation to how to get the url from WebClient in OpenReadCompleted?