|
I've set up a background worker thread to load images from a web service, but while it does that, my program becomes unresponsive. I call the method to load the image in my DoWork delegate, doesn't that mean it happens on the other thread ? I also had a progresschanged delegate, it just sets a position in a progress bar. With this in, it died right away. I took it out and it seemed to work, but when I gave the program focus, it immediately became unresponsive. In both cases, it's Not Responding in the Task Manager, and the UI no longer responds to any events. I'm running a debug version, in the IDE, when I break, it's always on the line in the other thread that loads an image from the web service. The main thread is not doing any work of any kind, in theory.
What might I be missing here ?
threadLoadCase = new BackgroundWorker();
threadLoadCase.DoWork += new DoWorkEventHandler(threadLoadCase_DoWork);
threadLoadCase.ProgressChanged += new ProgressChangedEventHandler(threadLoadCase_ProgressChanged);
threadLoadCase.WorkerReportsProgress = true;
threadLoadCase.RunWorkerCompleted += new RunWorkerCompletedEventHandler(threadLoadCase_RunWorkerCompleted);
void threadLoadCase_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.UserState != null)
lblLoadingCase.Text = "Downloading " + e.UserState.ToString() + ":";
progressLoading.Value = e.ProgressPercentage;
// Without this, the progress bar never showed at all.
Application.DoEvents();
}
void threadLoadCase_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Result.ToString()) && !firstFeedMe)
{
firstFeedMe = true;
filmStrip1.Clear();
OpenFiles(Directory.GetFiles((string)e.Result));
ResetDisplayMode();
}
}
void threadLoadCase_DoWork(object sender, DoWorkEventArgs e)
{
lblLoadingCase.Visible = progressLoading.Visible = true;
Application.DoEvents();
progressLoading.Value = 0;
e.Result = LoadCase(RequestIDs[0]);
}
and the guts of the method:
ImageInfo[] images = inbox.GetRequestImages(req.IdRequest);
int percentstep = 100 / (images.Length + 1);
int percent = percentstep;
foreach (ImageInfo inf in images)
{
// threadLoadCase.ReportProgress(percent, req.PatientName + req.OwnerLastName);
string imageFile = Path.Combine(folder, inf.ItemName);
if (!File.Exists(imageFile))
{
ImageData data = inbox.GetImageCompressed(inf.IdImage, dicomCompressionTypes.cmpJPEG2000);
using (FileStream fs = new FileStream(imageFile, FileMode.OpenOrCreate, FileAccess.Write))
{
fs.Write(data.Image, 0, data.Image.Length);
fs.Close();
}
}
percent += percentstep;
}
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
CG, you gotta set the example, man, and use <pre> tags around that code!
Just skimming the code, a couple things jump out at me. First, you're calling Application.DoEvents everywhere. In my experience, this is a bad idea, because you can start getting things like event handlers out of order if the DoEvents is called in certain places.
The lblLoadingCase is a label? If so, don't update that in DoWork. Same goes for the progress bar. The DoWork method is called on a background thread, the ProgressChanged and RunWorkerCompleted will be called from the UI thread. Accessing WinForm controls on a background thread is asking for trouble; VS2005 will actually throw an exception if this happens under the debugger.
As far as the freezing goes, my only guess is the ProgressChanged event is getting hammered; flooded with calls. Each call will require the UI thread to execute it obviously, so the if the UI thread is constantly busy, the UI won't have a chance to paint.
Here's what I recommend: first narrow the problem down, see if it's the ProgressChanged handler, let's see if it becomes responsive again. If it's responsive when you don't call ReportProgress, then you need to update the UI in a manner that allows the UI to still repaint itself. I have such a solution if you're interested; it's actually pretty easy to implement. But first try removing calls to ReportProgress, and see if the app is responsive again, then let me know.
If it's not that, it may be that your DoWork handler is being called on the UI thread, which would indicate you're not starting the work correctly or the worker wasn't initialized on the UI thread.
|
|
|
|
|
Judah Himango wrote: First, you're calling Application.DoEvents everywhere
Only because I'm trying to make the UI work at all, it's not being updated right now.
Judah Himango wrote: The lblLoadingCase is a label? If so, don't update that in DoWork.
Ah - good point. I AM in a debug build, but perhaps it's freezing when it means to be blowing up...
Judah Himango wrote: As far as the freezing goes, my only guess is the ProgressChanged event is getting hammered; flooded with calls
No, that's not possible. Each call is just before a web service call that takes a while. I also set a breakpoint to see, and it's not happening, only one call ever happens, although the UI does not repaint itself.
Judah Himango wrote: I have such a solution if you're interested; it's actually pretty easy to implement
OK - I'd be keen to see it, thanks.
I'm also going to put Console.WriteLine code throughout so I can see what's being called and where it's getting stuck.
Thanks.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
Judah Himango wrote: The lblLoadingCase is a label? If so, don't update that in DoWork
I'd say this was my whole problem. No error was raised, but I changed this and now it's all working oh so sweetly. Thanks for pointing out what should have been obvious )
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
|
Hi,
you as an old CPian should know better on how to format your posts .
Christian Graus wrote: // Without this, the progress bar never showed at all.
Application.DoEvents();
This tells me that your GUI thread is definitely doing a lot of work. What I'm missing in your code is on how you start the processing. It should be something like threadLoadCase.RunWorkerAsync() . Also I do not quite get to which method you refer to with and the guts of the method:. Do you mean LoadCase ? If not then where is this code called?
Robert
|
|
|
|
|
if (RequestIDs.Count < 5 && !threadGetRequests.IsBusy)
{
threadGetRequests.RunWorkerAsync();
}
This happens inside a button click. If RequestIDs > 5 then we don't need to go looking for more, we can just load one. That's the other thread, actually, but they both work the same sort of way.
if (timerLoadCases == null || !timerLoadCases.Enabled)
{
timerLoadCases = new System.Windows.Forms.Timer();
timerLoadCases.Interval = 5000;
timerLoadCases.Tick += delegate
{
if (RequestIDs.Count > 0 && !threadLoadCase.IsBusy)
{
threadLoadCase.RunWorkerAsync(RequestIDs[0]);
RequestIDs.RemoveAt(0);
}
};
timerLoadCases.Start();
}
This is the other one, if we have a RequestID to download and there's none downloading now, we start downloading one. This adds them to a queue, we view from the queue.
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
Hello,
After a long hours of search in google, I wasn't able to find what I was looking for. I need pointers on how to write an application that will let me manage network bandwidth throttling. I want to run a local cable network and instead of relying on a 3rd party software, I want to write on for the sake of learning something new. It surely sounds challenging but I didn't thought it would be that challenging, at beginning.
Anyways, I want to limit bytes / sec on a certain IP with ports range etc. Maybe few guides in the right direction please?
Any help will be appreciated.
Thanks
|
|
|
|
|
Very big job. You basically have to write a proxy service that takes in requests on one side, makes the outward connection to the requested address on the other side and then passes the data between the two connections at the throttle rate you configured.
Not REALLY difficult, but very difficult to do well. Covers lots of different areas (threading, sockets, streams, etc...)
While I admire your want to learn this, you might want to settle down a bit and pick PARTS of this problem and learn each one very well first.
|
|
|
|
|
Thanks for replying, Ray. Actually, I want to do it like SoftPerfect's Bandwidth Manager or NetLimiter, i.e. without using a proxy.
I do have some fair knowledge of threading, streams and basic knowledge of sockets but I am willing to spend much time to improve on these areas. There's no haste and I have lots of time on hands to learn all the required stuff. The bottomline is, I just want to do it whether I convert it to a full-blown software or not.
Basically, I am looking for guides on how network bandwidth limiting can be done on windows using C# .NET or maybe just generally. For a start, I will probably be testing it on my home network by limiting speed on all ports on my desktop PC.
Thanks for help.
|
|
|
|
|
it is a difficult thing to do. I think what you are trying to write is what's called a "traffic shaper". you will probably need some kind of a low level proxy, through which all data packets will go through, so that you can control the rate in which these packets are passed over the network.
This proxy would have to use something like the winpcap library (or libpcap if you're not working on windows).
anyway, good places to start are: this article[^], which uses raw sockets to handle packets, and this one[^], which ports winpcap to c#
there are no facts, only interpretations
|
|
|
|
|
Hi , did u find the way? i really need it!
|
|
|
|
|
Well with how well HttpWebRequest worked reading a file, i though FTP would be just a s easy, not quite so, i have:
FtpWebRequest request =(FtpWebRequest)WebRequest.Create(@"ftp://address/1.txt");<br />
request.Credentials = new NetworkCredential("username", "password");<br />
request.Method = WebRequestMethods.Ftp.AppendFile;<br />
Stream FS = request.GetRequestStream();<br />
StreamReader SR = new StreamReader(FS, true);<br />
string line = SR.ReadLine();
I imagined that that would read the file, i was wrong, says that the stream is not readable.
So apart from the not being able to read the file, i need to be able to edit the file, and there would be the possibility of multiple people trying to edit it at the same time, how would i do this?
(No two people would be editing the same line in the file, if that makes any difference at all)
So err, any help or suggestions would be great
|
|
|
|
|
Perhaps if you try the Download protocol instead of the AppendFile protocol. The AppendFile protocol is used to append a file to another on the FTP server.
You can't edit a file over FTP. You have to first download the file, edit it, and then upload it.
If multiple people should be able to edit the file, you would have to download the latest version of the file to match it with the edited version before you can upload it. Also you should use some way to lock the file while you are matching it, so that two people can't do a match at the same time, perhaps rename the file while you are working with it.
---
b { font-weight: normal; }
|
|
|
|
|
Hello,
I am not 100% sure about that, but the methods seem similar to the HttpRequest.
The "request stream" is not readable, because you make your request to the server through it, it is a writable stream. There is another stream, the "response stream" which is sent to you after you call GetResponseStream() at some class (guess it was the request, too).
Get request stream, write data into if you need, get response stream, read it.
Regards,
d.mon
|
|
|
|
|
ok i need help here, I'VE LOST MY TUTORIAL IN MY BOOK, i want to send this "A2S_INFO" to a server through UDP/IP, How can i recieve his reply?
is this how to send?
System.Net.Sockets.UdpClient b = new System.Net.Sockets.UdpClient(serv, port);
b.Send(Encoding.UTF8.GetBytes("A2S_INFO"), Encoding.UTF8.GetBytes("A2S_INFO").GetLength(0));
|
|
|
|
|
hello developers... best regards!
I need to know how to get the data available in the dataGrid and insert (by a certain way) into sql server db?? i mean determining a datasource for the datagrid is simple, using a dataset, but if i wanna get this dataset and insert its data into a certain sql server table, how would it be?
Plz i need your help in that...
Ur help is much appreciated!
Sincerly urs, ali.;)
Knowledge Is KinG
|
|
|
|
|
hi
i want to print datagrid in vc# 2005 (not datagridview), and i found an article and class for datagridprinter in Codeproject but it's in VB and not work in c# .. does any one know how to do this ?
thanks ...
|
|
|
|
|
Hello
Maaybe you can check out this article[^]. DotNet 2.0 is a prerequisite on the target machine.
Regards
|
|
|
|
|
csc /t:module c:\form4.cs c:\form5.cs
when i use csc.exe through the command line this works and form4.netmodule is generated in
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
problem1:
the compiler always generates the .netmodule files in the above folder
how can i specify a path where i want to generate the .netmodule file
Problem2:
i am trying to do this through windows application(c#)
i am using this command on button_click
Process.Start(@"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\\csc","/t:module c:\form4.cs c:\form5");
this command does not work properly
if there is some error in any file form4 or form5 it is indicated but when there is no error even then
the .netmodule file is not generated in the above mentioned folder
|
|
|
|
|
Hello,
you'll find CSC options in the MSDN documentation. /out specifies the output file, see: http://msdn2.microsoft.com/en-us/library/bw3t50f3.aspx
For compiling source code from within an application during runtime, I would suggest to make use of the System.CodeDom.Compiler classes (e.g. System.CodeDom.Compiler.CSharpCodeProvider) for compiling C#. There's also providers for other languages, unified under the ICodeCompiler interface (see MSDN).
Regards,
d.mon
|
|
|
|
|
I have a Client and a Sever, i connect the client to the server via Socket, now i'd like to send a file from the Client to the Server, i read about Socket.SendFile(fileName), but can't find how, from the server i have to receive the file using it (sendfile) in the client, i'd like to see an example, thank you!
|
|
|
|
|
Hy,
You don't need to send a file with the Send File method. The send method send a byte array. So use FileStream to read the byte content of the file and then send it to the client/server
FileStream fstream = File.Open(filename,FileMode.Open);
byte []buffer = new byte[fstream.Lenght];
fstream.Read(buffer,0,buffer.Length);
fstream.Close();
ClientSocket.Send(buffer);
It works fine on any kind of files. After you have received the file use FileStream to write the file (of course you should know the extension to put to the file).
Hope it helps
Do your best to be the best
|
|
|
|
|
I'm having problem in the Server Side;
How do i receive the file? and if i need the extension of the file, i have to send it with the client? and then how do i retrieve it? Thanks
else if (data.StartsWith("$UploadFile"))
{
}
|
|
|
|
|
You can create your own communication protocol. Let's say that the client sends a message to the server telling him that he will upload a file with a specified extension and size. The server sends back an acknowledge message and the the client sends the file.
Concerning the server. If you know the exact size of the file then you can do something like:
byte[] buffer = new byte[size];
client.Receive(buffer);
If you do not know the size of the file then you can write a sequence that reads data from the network in packets let's say 1024 long, like this:
ArrayList list = new ArrayList();
byte[] buffer = new byte[1024];
int read = 0;
int length = 0;
while ((read = client.Receive(buffer) != 0)
{
length += read;
list.Add(buffer);
buffer = new byte[1024];
if (read < 1024)
break;
}
At the end of this code you have inside the array list the entire file stored in 1024 length byte , arrays. After this just extract the byte arrays from the array list, like this.
buffer = new byte[length];
byte []temp = null;
int k = 0;
for (int i = 0 ; i < list.Count ; i++)
{
temp = (byte[])list[i];
for (int j = 0 ; j < temp.Length ; j++)
byte[k++] = temp[j];
}
Hope it helps.
Do your best to be the best
|
|
|
|
|