Winform becomes unresponsive

C

CannonFodder

Hi all, basically i have a WMI scanner which i install as a windows
service. using .NET remoting the service registers an object which
records the status of the scanner (ie how many assets its' scanned so
far etc..)

I then have a windows application which reads the status object to
display the progress of the scanner (ie which asset is it scanning and
an overall % complete)

This all works fine when i scan up to 50 assets but i am in the
process of load testing the scanner and am increasing the number of
scans to 100, 150 etc..

the scans do work but the windows application basically locks up for
the majority of the scan.

I have a thread on the scanner service which starts up the scan and
sleeps inbetween scans for x minutes.

the scanner itself uses a threadpool to scan all the assets on the
network and a thread to upload results to a webservice.

I am using a timer on the windows application to check the status
obejct every second and then display the results on the form, this
seems to be the bit that keeps locking up (only when lots of assets
are being scanned tho)

how can i keep my windows application responsive, no matter how many
assets i am trying to scan?
 
I

Imran Koradia

Which timer control are you using? There are 3 timer controls in .NET -
System.Windows.Forms.Timer, System.Timers.Timer, System.Threading.Timer. The
Forms Timer runs on the same thread as the UI. So if you are in fact using
that timer and you have a time consuming process within your tick event, the
UI would lock up. Is this the case for you?


hope that helps..
Imran.
 
G

Gavin Jackson

sounds like you may be on to something here, i am indeed using the forms
timer (drag and drop).

i'll play around with the other 2 types you mentioned and keep you
posted.

cheers
 
G

Gavin Jackson

i've tried all three types of timer with no effect it still locks up.

i have placed a label on my form which displays a counter, this updates
every second so i can see what is going on and my counter clearly
freezes during the execution of my application.

i have noticed the cpu usage on my machine also hits 100% during the
running of my application, could this cause my app to freeze up?
 
J

Jon Skeet [C# MVP]

Gavin Jackson said:
i've tried all three types of timer with no effect it still locks up.

i have placed a label on my form which displays a counter, this updates
every second so i can see what is going on and my counter clearly
freezes during the execution of my application.

i have noticed the cpu usage on my machine also hits 100% during the
running of my application, could this cause my app to freeze up?

Quite possibly.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
G

Gavin Jackson

errr, my last post didnt seem to appear, apologies if this comes up
twice

/*
Windows Application
------------------------
This is the 'status' application which regularly checks the status of
the REMOTE status object
and updates the UI accordingly, for the purposes of this example i am
only showing a timer ticking
rather than the whole UI, (it still hangs with the basic timer in place)
------------------------
*/
ThreadStart startDelegate = new ThreadStart(updateStatus);
Thread tStatusUpdater = new Thread(startDelegate);
tStatusUpdater.Priority = ThreadPriority.Highest;
tStatusUpdater.Start();

private void updateStatus()
{
for(;;)
{
nTimeTaken ++;
lbTimer.Text = nTimeTaken.ToString() + " secs";
Thread.Sleep(1000);

//loads of other stuff that updates progress bars etc.. but i've
removed all that
//and left this timer in here, which *should* tick every second, but
hangs every so
//often
}
}

/*
Windows Service
--------------------------
The windows service regularily sweeps the network and performs a WMI
scan of each asset on the domain (not shown, other classes)

The scan is probably the thing that bumps the CPU usage to 100% tho
(uses threadpools etc.)
--------------------------
*/
protected override void OnStart(string[] args)
{
myScanner = new DomainScanner();
Thread tScanDomain = new Thread(new ThreadStart(beginScanning));
tScanDomain.Start();
}
public static void beginScanning()
{
//make sure the config is ready and set up before proceeding with any
scans
if(myScanner.IsConfigLoaded == false)
{
myScanner.refreshConfig();
Thread.Sleep(10000);
beginScanning();
}
else
{
bool bAllowScan = true;
for(;;)
{
if(bAllowScan==true)
{
bAllowScan = false;
//this line actually fires the scanner - which scans every
//asset connected to the current domain - status object updated in
this method
myScanner.ScanDomain();
while(myScanner.IsFinished()==false)
{
//dont do anything until its finished
//wait for 10 secs and check again
Thread.Sleep(10000);
}
}
else
{
if(myScanner.IsFinished()==true)
{
bAllowScan = true;
myScanner.IsSleeping();

Thread.Sleep(myScanner.MSBetweenSweeps);
beginScanning();
}
}
}
}
}


/*
------------------------------
..NET REMOTE object (Scanner Status)

myScanner.ScanDomain(); scans the domain and as its doing so updates
this class
and tells it which computer is being scanned etc..
------------------------------
*/
public class ScannerStatus : MarshalByRefObject
{
public enum eStatus : byte
{
STARTED, STOPPED, QUEUEING, SCANNING, FINISHED, WAITING, READY,
SLEEPING
};

private eStatus myStatus;
private string strMessage;
private int nGoodScans = 0;
private int nBadScans = 0;
private int nScanNumber = 0;
private int nTotalADEntries = 0;

public eStatus Status
{
get
{
return myStatus;
}
set
{
myStatus = value;
}
}

public string Message
{
get
{
return strMessage;
}
set
{
strMessage = value;
}
}
etc...
}
 
G

Gavin Jackson

sorry, short AND complete might be a bit hard, here's long and
incomplete (its the best i could do)

/*
Windows Application
------------------------
This is the 'status' application which regularly checks the status of
the REMOTE status object
and updates the UI accordingly, for the purposes of this example i am
only showing a timer ticking
rather than the whole UI, (it still hangs with the basic timer in place)
------------------------
*/
ThreadStart startDelegate = new ThreadStart(updateStatus);
Thread tStatusUpdater = new Thread(startDelegate);
tStatusUpdater.Priority = ThreadPriority.Highest;
tStatusUpdater.Start();

private void updateStatus()
{
for(;;)
{
nTimeTaken ++;
lbTimer.Text = nTimeTaken.ToString() + " secs";
Thread.Sleep(1000);

//loads of other stuff that updates progress bars etc.. but i've
removed all that
//and left this timer in here, which *should* tick every second, but
hangs every so
//often
}
}

/*
Windows Service
--------------------------
The windows service regularily sweeps the network and performs a WMI
scan of each asset on the domain (not shown, other classes)

The scan is probably the thing that bumps the CPU usage to 100% tho
(uses threadpools etc.)
--------------------------
*/
protected override void OnStart(string[] args)
{
myScanner = new DomainScanner();
Thread tScanDomain = new Thread(new ThreadStart(beginScanning));
tScanDomain.Start();
}
public static void beginScanning()
{
//make sure the config is ready and set up before proceeding with any
scans
if(myScanner.IsConfigLoaded == false)
{
myScanner.refreshConfig();
Thread.Sleep(10000);
beginScanning();
}
else
{
bool bAllowScan = true;
for(;;)
{
if(bAllowScan==true)
{
bAllowScan = false;
//this line actually fires the scanner - which scans every
//asset connected to the current domain - status object updated in
this method
myScanner.ScanDomain();
while(myScanner.IsFinished()==false)
{
//dont do anything until its finished
//wait for 10 secs and check again
Thread.Sleep(10000);
}
}
else
{
if(myScanner.IsFinished()==true)
{
bAllowScan = true;
myScanner.IsSleeping();

Thread.Sleep(myScanner.MSBetweenSweeps);
beginScanning();
}
}
}
}
}


/*
------------------------------
.NET REMOTE object (Scanner Status)

myScanner.ScanDomain(); scans the domain and as its doing so updates
this class
and tells it which computer is being scanned etc..
------------------------------
*/
public class ScannerStatus : MarshalByRefObject
{
public enum eStatus : byte
{
STARTED, STOPPED, QUEUEING, SCANNING, FINISHED, WAITING, READY,
SLEEPING
};

private eStatus myStatus;
private string strMessage;
private int nGoodScans = 0;
private int nBadScans = 0;
private int nScanNumber = 0;
private int nTotalADEntries = 0;

public eStatus Status
{
get
{
return myStatus;
}
set
{
myStatus = value;
}
}

public string Message
{
get
{
return strMessage;
}
set
{
strMessage = value;
}
}
etc...
}
 
J

Jon Skeet [C# MVP]

Gavin Jackson said:
sorry, short AND complete might be a bit hard, here's long and
incomplete (its the best i could do)

Hmm. Looking at it very briefly, I note that you're calling
beginScanning from within beginScanning. Could it be that you're
getting a StackOverflowException, but not seeing it due to it being in
a different thread?

Try adding a handler to AppDomain.UnhandledException.
 
J

Jon Skeet [C# MVP]

Gavin Jackson said:
sorry, short AND complete might be a bit hard, here's long and
incomplete (its the best i could do)

/*
Windows Application
------------------------
This is the 'status' application which regularly checks the status of
the REMOTE status object
and updates the UI accordingly, for the purposes of this example i am
only showing a timer ticking
rather than the whole UI, (it still hangs with the basic timer in place)
------------------------
*/
ThreadStart startDelegate = new ThreadStart(updateStatus);
Thread tStatusUpdater = new Thread(startDelegate);
tStatusUpdater.Priority = ThreadPriority.Highest;
tStatusUpdater.Start();

private void updateStatus()
{
for(;;)
{
nTimeTaken ++;
lbTimer.Text = nTimeTaken.ToString() + " secs";
Thread.Sleep(1000);

//loads of other stuff that updates progress bars etc.. but i've
removed all that
//and left this timer in here, which *should* tick every second, but
hangs every so
//often
}
}

Eek - just noticed this bit. That's updating the UI from a non-UI
thread. Don't do that.

See http://www.pobox.com/~skeet/csharp/threads/winforms.shtml
 
G

Gavin Jackson

oh, i take it this is probably a bad thing then....

i'll put it back to the System.Timers.Timer thing

I called beginScanning() from within that method cos i want my scanner
to always doing something in that method, either scanning the network or
just sleeping waiting until the next time it should be scanning.

I suspect there is a better way of doing this.

cheers for the link, i'll have a look through it and see if i can
understand the code
 
J

Jon Skeet [C# MVP]

Gavin Jackson said:
oh, i take it this is probably a bad thing then....

i'll put it back to the System.Timers.Timer thing

Right. Then try getting a short but complete version which shows the
problem.
I called beginScanning() from within that method cos i want my scanner
to always doing something in that method, either scanning the network or
just sleeping waiting until the next time it should be scanning.

I suspect there is a better way of doing this.

Yes - just go round in a loop (eg using while(true)).
 
G

Gavin Jackson

Hey, thanks a lot! that link you sent me about threading in windows
forms seems to have done the trick, im running a test at the momement
which should have hung it by now, and its still all lovely and
responsive.

if anyone else is interested, i used the following code to update my UI
components within the threaded process:



delegate void delegateStrParam(string strString);

private void uiUpdatePercent(double nPercent)
{
if(InvokeRequired)
{
BeginInvoke(new delegateDblParam(uiUpdatePercent), new
object[]{nPercent});
return;
}
drawObj.setPercent(this,(int)nPercent);
labRemain.Text = string.Format("{0:N0}",nPercent) + "%";

}

thanks again for your help Jon
 
J

Jon Skeet [C# MVP]

Gavin Jackson said:
Hey, thanks a lot! that link you sent me about threading in windows
forms seems to have done the trick, im running a test at the momement
which should have hung it by now, and its still all lovely and
responsive.

Goodo - glad it worked :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top