BackgroundWorker Help needed - c#

I have code that does a web-service request.
While doing this request I need a progress-bar to be moving independently.
My problem is that I just need to say run a progress update every 1 or 2 seconds and check to see if progress of the request has been completed.
NetBasisServicesSoapClient client = new NetBasisServicesSoapClient();
TransactionDetails[] transactions = new TransactionDetails[dataGridView1.Rows.Count - 1];
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
transactions[i] = new TransactionDetails();
transactions[i].TransactionDate = (string)dataGridView1.Rows[i].Cells[2].Value;
transactions[i].TransactionType = (string)dataGridView1.Rows[i].Cells[3].Value;
transactions[i].Shares = (string)dataGridView1.Rows[i].Cells[4].Value;
transactions[i].Pershare = (string)dataGridView1.Rows[i].Cells[5].Value;
transactions[i].TotalAmount = (string)dataGridView1.Rows[i].Cells[6].Value;
}
CostbasisResult result = client.Costbasis(dataGridView1.Rows[0].Cells[0].Value.ToString(), dataGridView1.Rows[0].Cells[1].Value.ToString(), transactions, false, "", "", "FIFO", true);
string result1 = ConvertStringArrayToString(result.Details);

I use Background Workers all the time, they are great for processing long time actions.
from your code
#region Background Work of My Request
private void ProcessMyRequest()
{
if (!bkgWorkerMyRequest.IsBusy)
{
lblMessageToUser.Text = "Processing Request...";
btnProcessRequest.Enabled = false;
bkgWorkerMyRequest.RunWorkerAsync();
}
}
private void bkgWorkerMyRequest_DoWork(object sender, DoWorkEventArgs e)
{
// let's process what we need in a diferrent thread than the UI thread
string r = GetStuffDone();
e.Result = r;
}
private void bkgWorkerMyRequest_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
string myResult = (String)e.Result;
lblMessageToUser.Text = myResult;
btnProcessRequest.Enabled = true;
}
#endregion
private function string GetStuffDone()
{
NetBasisServicesSoapClient client = new NetBasisServicesSoapClient();
TransactionDetails[] transactions = new TransactionDetails[dataGridView1.Rows.Count - 1];
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
{
transactions[i] = new TransactionDetails();
transactions[i].TransactionDate = (string)dataGridView1.Rows[i].Cells[2].Value;
transactions[i].TransactionType = (string)dataGridView1.Rows[i].Cells[3].Value;
transactions[i].Shares = (string)dataGridView1.Rows[i].Cells[4].Value;
transactions[i].Pershare = (string)dataGridView1.Rows[i].Cells[5].Value;
transactions[i].TotalAmount = (string)dataGridView1.Rows[i].Cells[6].Value;
}
CostbasisResult result = client.Costbasis(dataGridView1.Rows[0].Cells[0].Value.ToString(), dataGridView1.Rows[0].Cells[1].Value.ToString(), transactions, false, "", "", "FIFO", true);
return ConvertStringArrayToString(result.Details);
}
all you need to do is call the method:
ProcessMyRequest();
and it will do the job. If you need to let the main Thread to be aware of progress, you can use the ProgressChanged event
private void bkgWorkerMyRequest_ProgressChanged(
object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
in the bkgWorkerMyRequest_DoWork method you need to change the code to have
//reports a percentage between 0 and 100
bkgWorkerMyRequest.ReportProgress(i * 10);
Remember:
alt text http://www.balexandre.com/temp/2010-04-07_1200.png
You will, however get stuck when trying to Debug the method GetStuffDone as it's that kinda hard debugging multi threaded applications
So, what I do is, debug everything without workers and then apply the workers.
Works fine for me, let me know if you need any more help on this.
added
I didn't aware that you were getting the Grid in the worker, sorry, for this, just send the grid as a argument and use it, please change:
bkgWorkerMyRequest.RunWorkerAsync(dataGridView1);
string r = GetStuffDone((GridView)e.Argument);
private function string GetStuffDone(GridView dataGridView1)

Create a BackgroundWorker (call the instance "bgw") and type "bgw.DoWork += " followed by TAB TAB. Visual Studio then generates the DoWork event handler method. Copy the code above into the handler and voila.
I don't think it makes sense for you to report progress, since your progress is determined by the duration of the web service request over which you have no influence (and you cannot break it into smaller tasks). As such, just display the "doing work" dialog and initiate the background task to call the web service. When it's done close the "doing work" dialog.

Related

How can I execute a method after a content page is visible in Xamarin Forms?

In my Xamarin Forms app made for android as of now, I have a stack layout that gets populated based on a list that needs to fetch data from local sqlite DB. The data is around 200 rows. The stack needs to be populated when the ContentPage appears in foreground.
Since this process takes a bit of time, the navigation to this page is taking some time which leads to poor performance of app.
I have added that refresh method in constructor of page and also have tried putting it in OnAppearing override method. But the transition occurs only when the stack is populated.
Is there any way to view the page to the user first (make navigation happen) and then populate the stack?
{
private string shipmentId;
public ScanOrderPage( string shipmentID)
{
InitializeComponent();
shipmentId = shipmentID;
TapGestureRecognizer tapEvent = new TapGestureRecognizer();
tapEvent.Tapped += Scan_Button_OnClicked;
clickFrame.GestureRecognizers.Add(tapEvent);
}
protected override async void OnAppearing()
{
base.OnAppearing();
await Initiator();
}
private async Task Initiator()
{
Indicator.IsVisible = true;
bool allGood;
if (!await App.Database.IsShipmentPresent(shipmentId))
{
int getBox = await new ShipmentBoxes().Get(shipmentId);
allGood = getBox == 1;
}
else allGood = true;
if (!allGood) return;
await Populate();
Indicator.IsVisible = false;
}
private async Task Populate()
{
BoxListStack.Children.Clear();
var shipmentData = await App.Database.GetShipmentBoxes(shipmentId);
if (shipmentData == null) return;
ShipmentIDText.Text = shipmentId;
FromText.Text = shipmentData?.FirstOrDefault()?.From;
ToText.Text = shipmentData?.FirstOrDefault()?.To;
TotalBoxesText.Text = "Total Boxes: " + shipmentData.Count.ToString();
int scanCount = 0;
for (int i = 0; i < shipmentData.Count; i++)
{
string boxCode = shipmentData.ElementAt(i).BoxCode;
if (shipmentData.ElementAt(i).Scanned) scanCount += 1;
else
{
int foo = boxCode.LastIndexOf("-", StringComparison.Ordinal);
boxCode = boxCode.Substring(0, foo + 1) + "XXXX";
}
BoxListStack.Children.Add(new ScanBoxes(shipmentData.ElementAt(i).Scanned)
{
Subject = shipmentData.ElementAt(i).Subject + " " + shipmentData.ElementAt(i).SubjectClass,
BoxCode = boxCode
});
}
ScanStatusText.Text = "Boxes Scanned: " + scanCount.ToString() + " | Boxes Pending: " +
(shipmentData.Count - scanCount).ToString();
}```
It is wrong to view that your problem is in timing. Your problem is that you are executing too much long running code on the UI thread which freezes UI. Obviously you could postpone that to the moment when the page is displayed (for example using the Timer), but the problem with frozen UI would remain just it would appear in a bit less annoying form.
As your code appears to have lines that require to be running on UI thread in order to avoid crashes I can't go line by line and fix the problem.
However to run on non-UI thread you use Task.Run . If you need to switch to the UI thread after that you use InvokeOnMainThread.
Why not try infinite scrolling. Load as you scroll through the list
https://youtu.be/sZq8K_64bc0

Error message "Cannot evaluate expression because the current thread is in a stack overflow state"

I'm trying to create a recursive call to a method but receive error:
Cannot evaluate expression because the current thread is in a stack
overflow state
Just a bit of a background, I'm migrating a PowerBuilder app. to a C#.NET windows app., the PB app. has a timer that is done programmatically which will execute the main method at a specific time. The PB code runs on two machines, one timer is set at the '0' mark and on machine #2, it is set at the 30 second mark.
PB code below:
ue_wait event:
gi_offset = //Global variable set at the application open event, equivalent to program.cs - main event. Will be 0 or 30 depending on the machine.
li_difference = Integer( String( Now(), 'ss')) //Gets the seconds from the current date time.
DO UNTIL li_difference = gi_offset
ls_status = 'current second: ' + String( Now(), 'ss') + ' starting on:' + String( gi_offset)// Builds a string to display in a static text control in PB, label in C#.
IF st_status.Text <> ls_status THEN st_status.Text = ls_status
Yield()
li_difference = Integer( String( Now(), 'ss'))
LOOP
//execute main processing method.
ue_action().
//End of event
ue_action event
Do main processing.
Call ue_wait()
My C# code below:
private void Form1_Shown(Object sender, EventArgs e)
{
ue_wait();
}
private void wf_actions_Load(object sender, EventArgs e)
{
//Should fire after all of the form has loaded.
Shown += Form1_Shown;
}
private void ue_wait()
{
long todays_date_in_seconds = DateTime.Now.Second;
long ll_global_offset = 0;
string ls_status = "";
todays_date_in_seconds = DateTime.Now.Second;
while (!(todays_date_in_seconds == ll_global_offset))
{
ls_status = "Current second: " + DateTime.Now.Second.ToString() + " starting on: " + ll_global_offset.ToString();
lbl_status.Text = ls_status;
todays_date_in_seconds = DateTime.Now.Second;
}
ue_action();
}
private void ue_action()
{
//After the main processing is done, it goes back to ue_wait().
ue_wait();
}
So I have tried the two possibilities that I found on the Inet:
this.Shown += new System.EventHandler(this.Form1_Shown);
this.Activated += AfterLoading;
However when calling ue_action I get the error below in the ue_wait event for both...
{Cannot evaluate expression because the current thread is in a stack
overflow state.}
Fails on the first line: long todays_date_in_seconds = DateTime.Now.Second;
I found the .NET timer but it does not allow you to set the Start at a specific point in time, ie: seconds, Timer.Start() = 0 mark or Timer.Start() = 30 second mark (30000 milliseconds). The interval is one part that would work as I could set it to execute every 60 seconds.
After doing some googling, because there is 'recursive' programming, this is causing the 'Stack Overflow', how can I avoid the 'Stack Overflow' in the .NET environment or would there be another way to do what I need to do in the C#.NET environment?
The simplest approach would be to use a 1s System.Windows.Forms.Timer, that's a no brainer:
// timer initialization, somewhere
timer = new System.Windows.Forms.Timer();
timer.Interval = 1000;
timer.Tick += Timer_Tick;
DateTime? _lastHandledTimestamp = null;
private void Timer_Tick(object sender, EventArgs e)
{
// get current timestamp
var currentTimestamp = DateTime.UtcNow;
var currentSecond = currentTimestamp.Second;
// not the correct second yet?
if (currentSecond <= TARGET_SECOND)
return;
// truncate seconds and check if we already handled this hh:mm
var flooredToNearestMinute = currentTimestamp.AddSeconds(-currentSecond);
if (_lastHandledTimestamp.HasValue &&
_lastHandledTimestamp.Value >= flooredToNearestMinute)
return;
// if we're here, we are good to go
_lastHandledTimestamp = flooredToNearestMinute;
DoStuff();
}
If you want to avoid triggering the tick event every second, use a System.Threading.Timer instead, and use its Timer.Change method to calculate the next time it needs to fire on each iteration.
Groo, thanks for the input on the timer, I tweaked it for what I need to do.
private void timer1_Tick(object sender, EventArgs e)
{
string ls_status = "";
var currentSecond = DateTime.Now.Second;
ls_status = "Current second: " + currentSecond.ToString() + " starting on: " + Il_offset.ToString();
lbl_status.Text = ls_status;
if (currentSecond == Il_offset && Ib_processing_completed)
{
//Main processing method
ue_action();
}
}
In the Tick event, I populate an instance variable of offset in the PageLoad, in this case it will be 1 or 31 and set a Boolean variable to true in the ue_action event after successful processing.
To get rid of the original problem, instead of doing recursive programming and looping, the Tick event was recommended instead which meets my needs.
Thank you, the .NET learning curve begins.
William.

Pause the while loop until the button is pressed w/o using event handler C#

I am struggling to workout how to create something that essentially pauses my while loop until my button1 is pressed, I know about the event handler button1_Click but I don't think that will work in this situation as I have lots of loops nested in each other on my form_load.
Any help would be highly appreciated!
This is a snipped of my code where I want the loop to be 'paused' with the notes:
while (reader2.Read())
{
QuestionSpace = Convert.ToString(reader2["Question Space"]);
label1.Text = QuestionSpace;
if (button1.Click = true) // if the button is clicked)
{
// continue with the while loop (I am going to add an INSERT SQL query in here later)
}
else
{
// pause until the button is pressed
}
}
My whole code for the form:
public partial class CurrentlySetTestForm : Form
{
private int QuestionID { get; set; }
private string QuestionSpace { get; set; }
public CurrentlySetTestForm()
{
InitializeComponent();
}
private void CurrentlySetTestForm_Load(object sender, EventArgs e)
{
string y = GlobalVariableClass.Signedinteacher;
MessageBox.Show(y);
Convert.ToInt32(y);
string connectionString = ConfigurationManager.ConnectionStrings["myconnectionstring"].ConnectionString;
SqlConnection connect = new SqlConnection(connectionString);
connect.Open();
SqlCommand command18 = new SqlCommand("SELECT [QuestionID] FROM QuestionStudentAssociation WHERE ( [StudentID]=#Signedinstudent)", connect);
command18.Parameters.AddWithValue("#Signedinstudent", y);
var reader = command18.ExecuteReader();
while (reader.Read())
{
QuestionID = Convert.ToInt32(reader["QuestionID"]);
SqlCommand command19 = new SqlCommand(#"SELECT [Question Space] FROM Questions WHERE ( [QuestionID] = #currentQID )", connect);
command19.Parameters.AddWithValue("#currentQID", QuestionID);
try
{
var reader2 = command19.ExecuteReader();
while (reader2.Read())
{
QuestionSpace = Convert.ToString(reader2["Question Space"]);
label1.Text = QuestionSpace;
if (button1.Click = true) // if the button is clicked)
{
// continue with the while loop (I am going to add an INSERT SQL query in here later)
}
else
{
// pause until the button is pressed
}
}
}
catch (SyntaxErrorException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
MessageBox.Show("Done one loop");
}
}
}
}
Sounds like your not ready to learn TPL
So maybe a BackgroundWorker , you can paint it on the form
To make the click cancel the background worker have a look at Cancel backgroundworker
I would some time to learn TPL as its going to create a simpler and more elegant solution.
As for pausing I would refactor the code, you should not keep the reader open waiting on the user.
You do want event-driven response to UI events, always. However, I guess that you don't want to split your logic into a state machine by hand (where each event triggers progress to the next state). Well, you're in luck, the C# compiler has some keywords to build state machines automagically so you don't have to manage the details.
There are actually two different mechanisms for continuation-passing style implemented in C#. The old one, yield return, works great if your UI events are pretty much interchangeable (or you're only interested in one). Works like this:
IEnumerator<int> Coroutine;
// this could be a Form_Load, but don't you need to get the user information before making the database connection?
void BeginQuiz_Click( object sender, EventArgs unused )
{
Coroutine = RunQA();
}
IEnumerator<int> RunQA()
{
// connect to DB
// show first question on UI
return ContinueQA();
}
IEnumerator<int> ContinueQA()
{
// you can use a while loop instead if you really want
for( int question = 0; question < questionCount; ++question )
{
// check answer
if (/* too many wrong answers*/) {
// report failure in DB
yield break;
}
// get next question from DB
// show new question on the UI
// wait for UI action
yield return question;
}
// report score in DB
// update UI with completion certificate
}
void AnswerButton_Click( object sender, EventArgs unused )
{
answer = sender;
Coroutine.MoveNext(); // MAGIC HAPPENS HERE
}
void TimeoutTimer_Tick( object sender, EventArgs unused )
{
answer = TimeoutTimer;
Coroutine.MoveNext();
}
The magic comes from yield return. Every time the function reaches yield return, the compiler saves what you were doing. When the button click event comes and calls MoveNext, the compiler generates code that starts where yield return paused everything, and keeps going from there until the next yield return.
Important note, the code inside ContinueQA doesn't start when RunQA() does return ContinueQA(); It actually starts on the first MoveNext(). So split your code between RunQA() and ContinueQA accordingly.
If you need different pause reasons at different places in your code, then async/await will be more helpful.
A better way to handle this would be the use of a timer. This would allow the form to draw it's controls and handle all input, such as clicking the button.
Adjust the timer interval (ms) to your needs.
Another way of doing this would be, as Mehrzad Chehraz said, to use multi-threading.
On a side note, I would strongly recommend condition checks over the try/catch checks if possible.
Enable/Disable the timer using the button and call the loop when the timer ticks.
Example:
Timer loopTimer = new Timer();
private void Form1_Load(object sender, EventArgs e)
{
loopTimer.Interval = 100;
loopTimer.Tick += loopTimer_Tick;
loopTimer.Enabled = true;
}
void loopTimer_Tick(object sender, EventArgs e)
{
//perform the loop here at the set interval
}
private void button1_Click(object sender, EventArgs e)
{
//pause/play the loop
loopTimer.Enabled = !loopTimer.Enabled;
}

C# Download lag

I have a serious problem. I'm currently doing a patcher program.
There's a "Patch" button in the program, and if the user click it, the download is starting.
There are currently 5 files that the program needs to download. The downloading is correct, this part of the program is working but when I click the Patch button, the program starts lagging, and I can't close, or change the position of it.
Here's the code:
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(this.download));
thread.Start();
}
public void download()
{
int downloaded = 0;
int all = 5;
WebClient myWebClient = new WebClient();
if (button1.InvokeRequired)
{
MethodInvoker MethodControll = new MethodInvoker(download);
this.button1.Invoke(MethodControll);
}
else
{
double state;
jelenlegidownload.Text = "alut.dll";
myWebClient.DownloadFile(Files.alutDLL, "alut.dll");
downloaded++;
state = downloaded / all * 100;
progressBar.Value = Convert.ToInt32(state);
progressBar.Refresh();
this.Refresh();
jelenlegidownload.Text = "BlackBox.dll";
myWebClient.DownloadFile(Files.BlackBoxDLL, "BlackBox.dll");
downloaded++;
state = downloaded / all * 100;
progressBar.Value = Convert.ToInt32(state);
progressBar.Refresh();
this.Refresh();
jelenlegidownload.Text = "DevIL.dll";
myWebClient.DownloadFile(Files.DevILDLL, "DevIL.dll");
downloaded++;
state = downloaded / all * 100;
progressBar.Value = Convert.ToInt32(state);
progressBar.Refresh();
this.Refresh();
jelenlegidownload.Text = "fltkdll.dll";
myWebClient.DownloadFile(Files.fltkdllDLL, "fltkdll.dll");
downloaded++;
state = downloaded / all * 100;
progressBar.Value = Convert.ToInt32(state);
progressBar.Refresh();
this.Refresh();
jelenlegidownload.Text = "glut32.dll";
myWebClient.DownloadFile(Files.glut32DLL, "glut32.dll");
downloaded++;
state = downloaded / all * 100;
progressBar.Value = Convert.ToInt32(state);
progressBar.Refresh();
this.Refresh();
The Files.cs:
public class Files
{
public static string alutDLL = "https://dl.dropbox.com/s/62tt9w194xefk7t/alut.dll?token_hash=AAHQmybYdR44TRrS9bWQWV7jlZBzZQ-mmmjNy1Kv_qR4cg&dl=1";
public static string BlackBoxDLL = "https://dl.dropbox.com/s/vtdrl8qdpky8p08/BlackBox.dll?token_hash=AAHCtQPBJ5s-3aL5B4FqrmOUIGP6BVvW8ZQeWd-xBzysTw&dl=1";
public static string DevILDLL = "https://dl.dropbox.com/s/spni307vmk4zng9/DevIL.dll?token_hash=AAEmZdQj3dv2NIEh6tcWwkgyJHCytSsX65QXZyNGY2Vl1w&dl=1";
public static string fltkdllDLL = "https://dl.dropbox.com/s/fsa29pelfwgk5ha/fltkdll.dll?token_hash=AAF55SuU_8bfli5gIiPpA-VLWUmZKLbOK-Ys8iokuJ8_XA&dl=1";
public static string glut32DLL = "https://dl.dropbox.com/s/cptiwxv17nhtywp/glut32.dll?token_hash=AAGCNXQPpwrByjp-uG_avBbkNyNjTfOJFxbY3ieNAfLzVw&dl=1";
}
How can I fix the lagging? (As I said before, if I click the "Patch" button, the files are downloading, but the program "stops")
To stop the download part of your application to block your UI part of the application, why don't you do the download job on a different thread. This way your UI will still be responsive even if the download has not been finished.
Edit: I think this is a great article that applies to your case:
http://www.developerfusion.com/article/4134/net-threading-part-i/
I think you have misunderstood InvokeRequired.
From MSDN:
Gets a value indicating whether the caller must call an invoke method
when making method calls to the control because the caller is on a
different thread than the one the control was created on.
Basically, you start your download on another thread. But since this will cause InvokeRequired to be true, you recall the method on the GUI thread, locking the application.
Does it work better if you remove this section?
if (button1.InvokeRequired)
{
MethodInvoker MethodControll = new MethodInvoker(download);
this.button1.Invoke(MethodControll);
}
Update
To rule out that your doing something wrong with your progress bar, try simplify your download method to this:
public void download()
{
WebClient myWebClient = new WebClient();
myWebClient.DownloadFile(Files.alutDLL, "alut.dll");
myWebClient.DownloadFile(Files.BlackBoxDLL, "BlackBox.dll");
myWebClient.DownloadFile(Files.DevILDLL, "DevIL.dll");
myWebClient.DownloadFile(Files.fltkdllDLL, "fltkdll.dll");
myWebClient.DownloadFile(Files.glut32DLL, "glut32.dll");
}
This should make the files downloaded without lag, but you want see any updates in your progress bar (obviously).

progressbar won't update with backgroundworker?

im making file transfer (Server-Client) TCP
i've already looked for same questions like this one .. but no answer worked for me ..
ProgressBar doesn't update with backgroundworker .. i've searched for tutorials to do this .. and i exactly followed the steps.
the form lags while sending and after the file sent.. the progressbar goes to 100%
The file sent succesfully the send method code works fine... my problem just with updating the progressbar .. how do i fix that ??
Here i call (backgroundWorker1.RunWorkerAsync)
public void Send(string destPath)
{
if (listView1.Items.Count > 0)
{
List<String> job = new List<string>();
job.Add(listView1.Items[0].ToolTipText);
job.Add(destPath);
backgroundWorker1.RunWorkerAsync(job);
}
}
DoWork Method
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
List<string> job = (List<string>)e.Argument;
SendFile(job[0],job[1]);
}
here's the SEND method which i use (backgroundWorker1.ReportProgress)
private void SendFile(string srcPath, string destPath)
{
string dest = Path.Combine(destPath, Path.GetFileName(srcPath));
using (fs = new FileStream(srcPath, FileMode.Open, FileAccess.Read))
{
try
{
long fileSize = fs.Length;
sizeAll = fileSize;
long sum = 0;
int count = 0;
data = new byte[fs.Length];
SendCommand("receive<" + dest + "<" + fs.Length.ToString());
while (sum < fileSize)
{
if (fileSize - sum < packetSize)
{
count = fs.Read(data, 0, (int)(fileSize - sum));
network.Write(data, 0, (int)(fileSize - sum));
}
else
{
count = fs.Read(data, 0, data.Length);
network.Write(data, 0, data.Length);
}
fs.Seek(sum, SeekOrigin.Begin);
sum += count;
sumAll += count;
backgroundWorker1.ReportProgress((int)((sum * 100) / fileSize));
}
network.Flush();
}
finally
{
CloseTransfer();
}
}
}
and here is backgroundWorker1_ProgressChanged
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBarFile.Value= e.ProgressPercentage;
}
Seems strange the you're able to assign a value to the a UI control from another thread without getting any exception. Or that is, may be, a real issue.
Like a first thing I would do, if the code of ProgressChanged is inside (say) WindowsForm class, write like this:
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
this.Invoke(new Action(()=>
progressBarFile.Value= e.ProgressPercentage;
));
}
Something like this.
Did you set?
worker.WorkerReportsProgress = true;
(Either in code or in the properties window)
EDIT:
Shouldn't you be reading like this
count = fs.Read(data, 0, packetSize);
instead of reading data.Length bytes? Since you set data = new byte[fs.Length] the file will be read all at once, instead of in little pieces, which is required in order to see the progress bar change progressively.
thanks for [Nikola Markovinović] his answer was:
the line that causes the error was :
data = new byte[fs.Length];
after correcting the code :
data = new byte[packetSize];
while (sum < fileSize)
{
count = fs.Read(data, 0, data.Length);
network.Write(data, 0, count);
sum += count;
backgroundWorker1.ReportProgress((int)((sum * 100) / fileSize));
}
network.Flush();
The background worker is dorking around on a new thread, therefore, calling anything back to the original form and its controls (or original thread) will require some delegation to accomplish what you desire. I have several code examples that I can share but they would take up far too much space here on this site. As a quick assistance, try some of this information from this site.
Background Worker with Delegates
Of course, you can always Google for more regarding threading, delegates, etc. I hope that helps.
Well it may be something quirky but always worth checking the steps its easy to overlook first:
Have you set WorkerReportsProgress on the BackgroundWorker to true?
Have you hooked up the ProgressChanged event to your event handler?
Finally just compare your solution to a sample at the link below - it may remind you of something you've forgotten to do:
http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

Categories

Resources