multithreading

I need to do multithreading. It is my fist attempt. It failed. This is the setup:

There is a form with tabControl and a few pages. There is a progress bar on one of them. It is supposed to measure progress of file downloading. WIthout multhithreading it is dead while the files are downloaded and then in the end it jumps to 100%.

This is what I did. Everything compiled but the progress never was activated even after the downloading was over. In other words my code actually made the things worse.

In the main form I put in this code at the start of procedure that is handling the download:

ThreadStart threadDelegate = new ThreadStart ( Work.DoWork );
Thread newThread = new Thread ( threadDelegate );
newThread.Start ( );

Then in the loop that does downloading I put this in:

Thread.Sleep ( 0 );
Work work = new Work ( );
work.data = prg; // prg is a calculated % of the work done.

After the loop ends there is a statement:

newThread.Abort();

In a separate *cs file I created a class like this:

class Work
{
public int data;
public static void DoWork ( )
{
Form1 ff1 = new Form1 ( ); // Form1 is my main form
Work works = new Work ( );
ff1.progressBar_Gr1pg3.Value = works.data; // this is the progress bar on page3
}
}

I hope I did not miss anything essential. As I said I never saw any fruit of this code.

It is a test code for me. In fact I can live without this progress bar. I need multithreading for other things.

Please help.

[1625 byte] By [AlexBB] at [2007-12-24]
# 1

I just had a similar situation, and I got rid of the timer altogether. Instead I used the backgroundWorker component:

http://msdn2.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Good luck,
Russ

RussPerna at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 2
Well, it is an unexpected solution! Thank you. Maybe it is the way to go. I've already put some code in and it compiled.
AlexBB at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 3

privatebool DownloadFile(string sURL,ProgressBar pProgress,string Filename)

{

System.Net.HttpWebRequest URLReq;

System.Net.HttpWebResponse URLRes;

System.IO.FileStream FileStreamer;

byte[] bBuffer =newbyte[1024];

int iBytesRead = 0;

try

{

FileStreamer =newFileStream(Filename, System.IO.FileMode.Create);

URLReq = (HttpWebRequest)System.Net.WebRequest.Create(sURL);

URLRes = (HttpWebResponse)URLReq.GetResponse();

using (Stream sChunks = URLReq.GetResponse().GetResponseStream())

{

pProgress.Maximum =Convert.ToInt32(URLRes.ContentLength);

do

{

iBytesRead = sChunks.Read(bBuffer, 0, 1024);

FileStreamer.Write(bBuffer, 0, iBytesRead);

if (pProgress.Value + iBytesRead <= pProgress.Maximum)

{

pProgress.Value += iBytesRead;

}

else

pProgress.Value = pProgress.Maximum;

}

while (iBytesRead != 0);

pProgress.Value = pProgress.Maximum;

sChunks.Close();

FileStreamer.Close();

returntrue;

}

}

catch (Exception ee)

{

MessageBox.Show(ee.Message);

returnfalse;

}

}

cablehead at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 4

Hi cab,

This is cute but does not seem to be a separate thread. Could you comment on the advantage of this code from your point of view?

It seems to me pretty much what I have got or close.

I wish I could give you a job:)

Thanks

AlexBB at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 5

Russ hi,

If you have a chance to read this: I got the BacgroundWorker working. It definitely runs and performs as needed with one minor but nasty surprise. It does not handle the progress bar. I mean it showed me the final result only, pretty much as I had before. The progress bar was blank during the procedure (file downloading) and after downloading was finished it went all the way up.

I set WorkerProgressBar = true; I do not know what else I can do for it to work.

Any suggestions?

Also it refused to interact with any user-interface controls along the way. This is of course a part of the class description. There is a warning about it. So I have to do some additional coding but since the progress bar does not work, it is unclear if the other controls (label, textBox) will be reactive either.

Did you get your progress bar working?

In any event I needed multithreading for other things more than for this. From this standpoint I am quite grateful to you for the suggestion.

Thanks.

AlexBB at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 6

"I set WorkerProgressBar = true;"

That should have been: worker.WorkerReportsProgress = true;

Sorry.

AlexBB at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 7

It sounds like you aren't updating the progressBar while the second thread is executing.

I'm not sure what your processing is, but for example if you were using a loop:

i = 1;
for (i = 1; i <= 1000; i++)
{

//do your work here

currentLoop = i;
(sender as
BackgroundWorker).ReportProgress(currentLoop);
}

RussPerna at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 8

Heres a threaded version:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.IO;

using System.Net;

namespace WindowsApplication1

{

publicpartialclassForm1 :Form

{

public Form1()

{

InitializeComponent();

}

privatevoid backgroundWorker1_DoWork(object sender,DoWorkEventArgs e)

{

DownloadFile("http://download.freewarefiles.com/files/foobar2000_0.9.4.exe","C:\\test.exe");

}

bool pMaxSet;

privatevoid backgroundWorker1_ProgressChanged(object sender,ProgressChangedEventArgs e)

{

if (!pMaxSet)

{

pMaxSet =true;

progressBar1.Maximum = e.ProgressPercentage;

return;

}

progressBar1.Value = e.ProgressPercentage;

}

privatevoid backgroundWorker1_RunWorkerCompleted(object sender,RunWorkerCompletedEventArgs e)

{

MessageBox.Show("Download Complete");

}

privatevoid DownloadFile(string sURL,string Filename)

{

System.Net.HttpWebRequest URLReq;

System.Net.HttpWebResponse URLRes;

System.IO.FileStream FileStreamer;

byte[] bBuffer =newbyte[1024];

int pMax = 0;

int pValue = 0;

int iBytesRead = 0;

FileStreamer =newFileStream(Filename, System.IO.FileMode.Create);

URLReq = (HttpWebRequest)System.Net.WebRequest.Create(sURL);

URLRes = (HttpWebResponse)URLReq.GetResponse();

using (Stream sChunks = URLReq.GetResponse().GetResponseStream())

{

pMax =Convert.ToInt32(URLRes.ContentLength);

backgroundWorker1.ReportProgress(pMax);

do

{

iBytesRead = sChunks.Read(bBuffer, 0, 1024);

FileStreamer.Write(bBuffer, 0, iBytesRead);

if (pValue + iBytesRead <= pMax)

{

pValue += iBytesRead;

backgroundWorker1.ReportProgress(pValue);

}

else

backgroundWorker1.ReportProgress(pMax);

}

while (iBytesRead != 0);

backgroundWorker1.ReportProgress(pMax);

sChunks.Close();

FileStreamer.Close();

}

}

privatevoid Form1_Click(object sender,EventArgs e)

{

backgroundWorker1.RunWorkerAsync();

}

}

}

cablehead at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 9

(sender asBackgroundWorker).ReportProgress(currentLoop);

So far no luck--the same thing: not updating.

AlexBB at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 10

Alex,

Could you post your code?

Thanks,
Russ

RussPerna at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 11
Russ, it is a lot of code. Specifically, what part do you want?
AlexBB at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 12

Basically the section where you are updating the backgroundWorker component.

It should be working, so I'd like to see what's going on.

Thanks,
Russ

RussPerna at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 13

Thank you. This is the routine you may be looking for. I did some minor surgery on it for clarity. Hopefully I did not remove anything essential:)

public TimeSpan subPushHTTPrequestAll_Click ( BackgroundWorker worker, Object sender, DoWorkEventArgs e )
{
string symbol;
int numberToDownload = this.comboSymbols.Items.Count - 1;
Class2 class2 = new Class2 ( );
ThreadStart threadDelegate = new ThreadStart ( Work.DoWork );
Thread newThread = new Thread ( threadDelegate );
newThread.Start ( );
DateTime dateTimeStart = System.DateTime.Now;
// one way to get all .csv files is:
// process the list of files found in the directory.
string thePath = Application.StartupPath;
string cur_drive = thePath.Substring ( 0, 2 );
string targetDirectory = cur_drive + @"\VFP_Projects\Data\Stoxx\";
string[] fileEntries = Directory.GetFiles ( targetDirectory );
char[] delim = {'\\'};
string[] namesArr = new string[1];

// second way is to get them from ComboSymbols.DataSource

for ( int ii = 0; ii <= this.comboSymbols.Items.Count - 1; ii++ )
{
symbol = ( string )this.comboSymbols.Items[ii];
symbol = symbol.Trim ( );
int switched = ( ii + 1 ) % 10;

float proggr = ii / numberToDownload * 100f;
int prg = (int) proggr;
(sender as BackgroundWorker).ReportProgress ( prg );
Boolean returns = class2.getOneCSVfromYahoo ( symbol );
if ( returns != true )
{
Console.WriteLine ( "COULD NOT REFRESH: ", symbol );
Console.WriteLine ( symbol );
}
else
{
// will see if the company name is missing in correlates.dbf
if ( Globals.flaggedEmpty == true )
{
string sql1 = "SELECT * FROM 'correlates.dbf'";
string inpStr1 = "stoxx";
DataTable dt1 = Class2.getData ( sql1, class2.getConnStrings ( ref inpStr1 ) );
foreach ( DataRow row in dt1.Rows )
{
if ( (( string )row["named"]).Trim ( ) == "" )
{
Console.WriteLine ("empty: {0} ", ( string )row["named"] );
row["named"] = Globals.named;
Console.WriteLine ( "changed?: {0} ", ( string )row["named"] );
}
}
dt1.AcceptChanges ( );
}
}
} // end of loop for all companies. The company name ends up in Globals.named
DateTime dateTimeEnd = DateTime.Now;
TimeSpan span = dateTimeEnd - dateTimeStart;
Console.WriteLine ( "the time spent : {0}", span );
return span;
}

AlexBB at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...
# 14

I'm by no means an expert, but I feel like I am missing something here. Why not just use:

(sender as BackgroundWorker).ReportProgress(ii);

It seems like you are doing extra math and casting that isn't necessary.

Let me know if that make any difference.

Thanks,
Russ

RussPerna at 2007-10-8 > top of Msdn Tech,Visual C#,Visual C# General...