New to threading in C#

toekramp

Diamond Member
Jun 30, 2001
8,426
2
0
I have a winform that monitors several folders for new/changed files, and then parses them and inserts them into a database. This process can take several minutes or longer depending on the length of the file. Basically, each time a new file is dropped in, I'd like my app to check if there are any processes currently busy, and if not, then create a new thread and run the method.

public partial class Form1 : Form
{

private BackgroundWorker backgroundWorker1 = new BackgroundWorker();

public eBoardMonitor()
{
InitializeComponent();
}

private void btnMonitor_Click(object sender, EventArgs e)
{

this.backgroundWorker1.DoWork +=
new DoWorkEventHandler(backgroundWorker1_DoWork);
this.backgroundWorker1.RunWorkerCompleted +=
new System.ComponentModel.RunWorkerCompletedEventHandler(
this.backgroundWorker1_RunWorkerCompleted);
this.backgroundWorker1.RunWorkerAsync();


localWatcher.EnableRaisingEvents = true;
pdaWatcher.EnableRaisingEvents = true;
}


void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{

fileWatch.CheckExisting();

}

private void backgroundWorker1_RunWorkerCompleted(
object sender, RunWorkerCompletedEventArgs e)
{
this.txtLog.Text += "Completed"
}
 

Crusty

Lifer
Sep 30, 2001
12,684
2
81
You can use a ThreadPool with a MaxThread of 1 to only allow one background task at a time.
 

Crusty

Lifer
Sep 30, 2001
12,684
2
81
The other more 'manual' way is to use a blocking Queue to queue work items, and create your own thread that processes one work item at a time from the Queue.
 

toekramp

Diamond Member
Jun 30, 2001
8,426
2
0
Perhaps I'm missing something silly.

ThreadPool.SetMaxThreads(1,1);

ThreadPool.QueueUserWorkItem(new WaitCallback(ExecuteFiles));


private void ExecuteFiles(object state)
{
FileWatch fileWatch = new FileWatch(this.file);
fileWatch.ExecuteFiles();

}

It gets to the fileWatch.ExecuteFiles(); but doesn't seem to actually initiate it. I've tried stepping into the process while debugging at that point and it just goes to the end of the method. What am I missing?
 

JasonCoder

Golden Member
Feb 23, 2005
1,893
1
81
Originally posted by: Crusty
The other more 'manual' way is to use a blocking Queue to queue work items, and create your own thread that processes one work item at a time from the Queue.

This. I'm not sure about the sanity of setting the thread pool limit. Isn't the thread pool shared by all managed code? From the Remarks on ThreadPool.SetMaxThreads:

Use caution when changing the maximum number of threads in the thread pool. While your code might benefit, the changes might have an adverse effect on code libraries you use.

Just use a Queue and a separate thread sync'd with WaitHandles. There's a well defined pattern around this that I've implemented several times but I'm not on that box at the moment. Google it up.
 

imported_Dhaval00

Senior member
Jul 23, 2004
573
0
0
Originally posted by: KB
To monitor folders for changes I would recommend you use a FileSystemWatcher class.

http://msdn.microsoft.com/en-u...filesystemwatcher.aspx

There are issues with the FSW class - they are not necessarily bugs in the API, but the way the native OS (Windows) stack handles applications like Notepad. Also, in times of high loads, I have personally seen the FSW "leak" events - i.e. it won't raise the proper events when you're dumping hundreds of files into a folder within a very short span of time.

In any case, the issue is widely discussed and there are many [easy, simple] workarounds.



Originally posted by: Crusty
You can use a ThreadPool with a MaxThread of 1 to only allow one background task at a time.

No offense, but this is bad juju, man.



Perhaps I'm missing something silly.

ThreadPool.SetMaxThreads(1,1);

ThreadPool.QueueUserWorkItem(new WaitCallback(ExecuteFiles));


private void ExecuteFiles(object state)
{
FileWatch fileWatch = new FileWatch(this.file);
fileWatch.ExecuteFiles();

}

Don't be messing around with the ThreadPool - it is a CLR-level structure and the entire Framework depends on it. Microsoft has regretted putting this feature in the API. Also, 'watching' files is by all means a long-running task. You should be using a dedicated background thread [depending on the scope of the application].

If you still want to use a ThreadPool, look up "the managed threadpool" which allows you to create your own pool of threads and queue tasks outside of the CLR ThreadPool.
 

Crusty

Lifer
Sep 30, 2001
12,684
2
81
Originally posted by: Dhaval00
Originally posted by: KB
To monitor folders for changes I would recommend you use a FileSystemWatcher class.

http://msdn.microsoft.com/en-u...filesystemwatcher.aspx

There are issues with the FSW class - they are not necessarily bugs in the API, but the way the native OS (Windows) stack handles applications like Notepad. Also, in times of high loads, I have personally seen the FSW "leak" events - i.e. it won't raise the proper events when you're dumping hundreds of files into a folder within a very short span of time.

In any case, the issue is widely discussed and there are many [easy, simple] workarounds.



Originally posted by: Crusty
You can use a ThreadPool with a MaxThread of 1 to only allow one background task at a time.

No offense, but this is bad juju, man.

It was just a suggestion, I would never personally do that :p hence why I later mentioned using blocking Queues, my preferred way of queuing items for background tasks.

I use the ThreadPool implicitly using ASyncCallbacks to multiplex incoming data on sockets and setting the Max thread count to 1 would be silly!