我应该使用Backround工作者还是编写我自己的线程

时间:2016-03-23 19:32:40

标签: c# .net winforms

所以我们有一个程序在主UI中有一个暂停按钮。当按下暂停按钮时,保存时间戳,然后再次按下时,会创建另一个时间戳,计算两者之间的时间差异,然后使用{{1}将所有3个值和用户名一起发送到数据库。 }。问题是,如果快速按下按钮多次,则会发送所有数据的问题。

我有一个想法是创建一个队列,而不是暂停按钮发送数据,它会将它写入队列,然后有一个单独的线程检查队列并处理发送的句柄。

使用计时器每x秒触发一次后台工作程序,用于读取队列和发送数据的简单任务,如果它感觉像是过度杀戮/滥用。我是对的,这更像是常规的线程工作,还是背景工作者的方式?

3 个答案:

答案 0 :(得分:2)

我会使用包含在BlockingCollection类中的ConcurrentQueue,并使用Task来观察集合。

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

类Entry是您想要一次录制的任何内容的容器。

消费者任务如下所示:

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

要向队列添加条目,请执行以下操作:

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

完成添加条目后,请将其命名为:

pendingEntries.CompleteAdding();

完成处理当前队列中的条目后,任务将脱离 foreach 循环。

然后,您可以等待任务完成:

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

答案 1 :(得分:0)

我个人使用线程。 Backgroundworkers为我占用了太多代码。如果您将线程作为全局变量,则可以随意终止或启动线程。

看看这里:BackgroundWorker vs background Thread

对于线程和背景工作者,您都可以看到它们是否正在运行。如果它们正在运行,那么你可以在按钮运行时禁用该按钮,或者使按钮无效。对于你正在做的事情,我推荐背景工作者。

答案 2 :(得分:0)

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);            
    }