简体   繁体   中英

Should I use a Backround worker or write my own threads

So we have a program that has a pause button in the main UI. When the pause button is pressed a time stamp is saved and when pressed again another timestamp is then created, the time diff between the two is calculated and then then all 3 values along with a user name are sent to a db using WebClient . The problem is that if the button is pressed multiple times rapidly the there are issues with getting all the data sent.

I had the idea to make a queue and instead of the pause button sending the data it would write it to a queue and then have a separate thread check the queue and handle the handle the sending.

Using a timer to fire a background worker every x-seconds for the simple task of reading a queue and sending data if its there feels like overkill/abuse. Am I right and this is more of regular thread kind of job or is the background worker the way to go?

I would use a ConcurrentQueue wrapped in a BlockingCollection class, and use a Task to watch the collection.

var pendingEntries = new BlockingCollection<List<Entry>>(new ConcurrentQueue<List<Entry>>());
var loggingTask = System.Threading.Tasks.Task.Factory.StartNew(ConsumerTask, pendingEntries);

The class Entry is a container for whatever you want to record at once.

The consumer task looks like this:

private void ConsumerTask(object parameter) 
{
    var localPendingEntries = (BlockingCollection<List<Entry>>)parameter;
    foreach (var entry in localPendingEntries.GetConsumingEnumerable())
    {
       // push the 'entry' where you want.
    }
}

To add entries to the queue do this:

var newEntry = new Entry(......);
pendingEntries.Add(newEntry);

When you are done adding entries, call this:

pendingEntries.CompleteAdding();

The task will fall out of the foreach loop once it has finished processing the entries currently in the queue.

You can then wait for the task to complete with:

loggingTask.Wait();
pendingEntries.Dispose();

I personally use threads. Backgroundworkers take up too much code for me. If you have the thread as a global variable, you can kill or start the thread at will.

Take a look here: BackgroundWorker vs background Thread

For both a thread and backgroundworker you're able to see if they're running. If they're running then you're able to either disable the button if it's running or make it so the button does nothing. For what you're doing, I recommend background worker.

protected void btnPause_Click(object sender, EventArgs e)
    {
        System.ComponentModel.BackgroundWorker disableWorker = new System.ComponentModel.BackgroundWorker();
        disableWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(disableWorker_DoWork);
        disableWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(disableWorker_RunWorkerCompleted);
        disableWorker.RunWorkerAsync();
    }

    void disableWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        btnPause.Enabled = true;
    }

    void disableWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        btnPause.Enabled = false;
        System.Threading.Thread.Sleep(10000);            
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM