BackgroundWorker in .NET CF 2.0

  • Thread starter Thread starter davis
  • Start date Start date
D

davis

Hi, I guess there is no BackgroundWorker in CF 2.0, but is there some
other easy way to launch a quick background thread task from the UI?

I have a debug console logger, and it takes a while to fire up and
connect to a remote TCP server...and when it starts up, it causes
program start lag.

I could --

a) Add a UI control to initialize it
b) Spawn a new Thread(ThreadStart(initLogger));

Is there a better way?
 
Hi Chris, Thanks for the response.

Quick follow-up question...I'm not a wizard with this...still learning.
I tried using a thread pool to get the job done.

So, I have the method like this:

private void initDebug(object state) {

/* init debug TCP console here */

}

and in the main form constructor I have:

ThreadPool.QueueUserWorkItem(initDebug);

This seems to work ok...however when I kill the application, and I try
to re-deploy, I notice that it fails because the DLL i use for tcp
debug is in use.

I learned the hard way about the MinimizeBox property on CF forms. So,
I set this property to false, and I override the OnClosing method with
this:

protected override void OnClosing(CancelEventArgs e) {
e.Cancel = ShutDown( );
base.OnClosing(e);
}

where ShutDown( ) is my own method that tries to dispose of all
threads, sockets, etc.

It catches any exceptions and returns false if caught, otherwise it
returns true.

So, when I close the application, I see that the process is not listed
in the running processes on the PocketPc, but still, something has a
hold on this DLL, which leads me to have to reboot the device every
time.

Any ideas on what I'm doing wrong here?

Thanks in advance,
davis
 
You have to be a bit more precise with your description.

"kill" an application, how? If it is just through the OK button then you are
not killing, it you are closing it, which is fine.

It sounds like your ShutDown method isn't really getting rid of the threads.
How are you trying to do that? If the thread is blocked on something you
will have to design a mechanism to *ask* the thread to terminate. An example
of how to use windows events to signal to a thread to terminate is here:
http://www.danielmoth.com/Blog/2004/11/dont-poll.html

Note that ThreadPool threads are not meant to be used for long running tasks
or for blocking operations. For that, you should use a dedicated thread.
Unless you are running against v1.0 of the NETCF where the pool has 256
rather than 25 (or you are on v2.0 but have tweaked the maximum).

It sounds like you are using the running programs list on the device to tell
if your app is running. That is not god enough as it only shows the top
level windows with a caption. Use the Remote Process Viewer from the Remote
Tools menu under the Visual Studio menu from your Start menu. Then you can
tell for sure if your app has exited or not.

Cheers
Daniel
 
Hi Daniel,

Thanks so much for the response. Here is a bit more precision, I hope.
I'm making use of this handy utility so I can log debug messages to
the command line on my development laptop ->

http://www.codeproject.com/csharp/compacttcptrace.asp?df=100&forumid=24359&exp=0&select=846907

This builds a .dll which I include in my application. It has a static
method to initialize itself where it reads an xml config file to get
the IP/Port of the remote console, and makes a TCP socket connection to
it.

This is expensive and timely when starting up my application. So I do
the following in my main form:

private Thread debug = null;

private void MainForm_Load(object sender, EventArgs e) {
#if DEBUG
debug = new Thread(new ThreadStart(initDebugConsole));
debug.Start();
#endif
}

private void initDebugConsole() {
// for debugging to a remote console
try {
TcpTraceListener.InstallTcpTraceListener();
Debug.WriteLine("Debug Console Ready...");
} catch (Exception e) {
/*
* try/catch block here, b/c if you don't have the tcp
server
* running to catch debug log statements, it crashes
the app.
*/
SetText(e.Message);
}
}

There is no while loop in the method for that ThreadStart, so once it
completes, it should complete. I believe the reason it hangs when I
try to re-deploy is that the socket is still open, despite the
TcpTraceListener code having the following:

public override void Close() {
if (stream != null) {
try {
SendString(end);
stream.Flush();
stream.Close();
stream = null;
} catch {
}
}
if (tcpClient != null) {
try {
tcpClient.Close();
tcpClient = null;
} catch (Exception) {
}
}
}

public void Dispose() {
Close();
}

I even added a static ShutDown( ) method to the TcpTraceListener code
that does the same thing:

public static void ShutDown() {
if (stream != null) {
SendString(end);
stream.Flush();
stream.Close();
stream = null;
}
if (tcpClient != null) {
tcpClient.Close();
tcpClient = null;
}
}

and in my form I do the following:

private Boolean shutdown() {
SetText("Shutting down....");
try {
TcpTraceListener.ShutDown( );
} catch (Exception) {
return false;
}
return true;
}

/// <summary>
/// Callback when form is closing
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected override void OnClosing(CancelEventArgs e) {
e.Cancel = shutdown();
base.OnClosing(e);
}

I guess the only thing I haven't commented on is the SendString(end);
call above in the ShutDown method -- this sends a poison pill to the
server to indicate the session is closing, so the server can print a
msg to the console that the client shut down.

If you can spot something in here that can cause the socket to stay
open, I'd love to hear it.

Thanks much in advance,
Davis
 
Well I haven't looked at the detail of all that as I don't have the time
right now (but Chris has loads of time so he might...)

I certainly don't like all those statics, or all those empty catch handlers
that swallow exceptions and not reporting them. Did you verify that the
process stays up with remote process viewer like I suggested? Have you
single stepped into the code when you close the form to see what code path
it takes?

More importantly, why are you using a utility that was written to overcome a
limitation of netcf v1/VS.NET2003 that has been rectified in v2/VS2005?
http://www.danielmoth.com/Blog/2004/11/debugwriteline.html

Cheers
Daniel
 
Hi Daniel...well, you asked for more detail :)

I followed your link. I'm not sure what exactly you mean about this
limitation being rectified in v2/VS2005. From your blog:

"Send the output back to the dev machine, e.g. like that or that"

The "that" hyperlink is a link to the TcpTraceConsole -- which is
exactly what I'm using.

That's what I spawn a worker thread to initialize, b/c it seems to take
about 10 s to properly init itself. Incidentally, that's also the code
with all the statics and the empty exception handling.

Great tip on the Remote process viewer. I did not even know that
existed. Indeed, sometimes I saw my app still running.

I think I actually worked through this issue since my last post. I
have the following ->

private void ManForm_Closing(object sender, CancelEventArgs e)
{
try {
TcpTraceListener.ShutDown();
debug.Abort();
controller.Reset();
Manager.GetManager().Dispose();
} catch (Exception) {
// ignore
}
this.Close();
}

A method which I have to chuckle at. How many different synonyms are
there for "shut something down"? I think it uses most of them.

cancel, closing, shutdown, abort, reset, dispose, close
 
Just use Debug.WriteLine

Read the entire blog entry please, including:

"UPDATE:
Visual Studio 2005 (and .NET Compact Framework v2.0) support
Debug.WriteLine :-D"

Cheers
Daniel
 
Missed that...

Still, it seems I may have a problem. I'm guessing that in order for
Debug.WriteLine( ) to work on PocketPC the device has to be in the
cradle (i.e. connected to USB), so it is also connected to VS2005?

If this is the case, I'm out of luck, b/c the horrible WiFi management
software kills the wi-fi driver whenever the device is in the cradle.
I can't keep a connection, and the only way I can test anything that
has to do with sockets is to pull it out of the cradle.

If there is some other workaround like a NetworkTraceListener that can
be added to Debug.Listeners, please let me know...but then again, I'm
back to what I started with I guess ?
 
Back
Top