【问题标题】:How can I avoid global variables in a Threaded application如何避免线程应用程序中的全局变量
【发布时间】:2018-11-17 05:52:19
【问题描述】:

我制作了一个简单的应用程序,它使用后台工作程序调用执行缓慢的任务。我希望能够将一些参数传递给慢速函数并在任务完成时获得结果。我可以通过使用全局变量 a、b 和产品来做到这一点。 有没有更好的方法将参数传递给慢速函数并取回结果?

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

using System.Threading;
using System.ComponentModel; // for BackgroundWorker

namespace ThreadsDelegate
{
    /// <summary>
    /// Description of MainForm.
    /// </summary>
    public partial class MainForm : Form
    {
        Random rnd = new Random();
        int a; // will be used by the slow task
        int b; // will be used by the slow task
        string product = null; // we get back the result of the slow task
        int i = 0; // counter

        public MainForm()
        {
            InitializeComponent();
            listBox1.Items.Add("Starting a long task of multiplication, that takes a few seconds.");
            listBox1.Items.Add("We can still use the form interface for other activities, such as generating random numbers...");
            listBox1.Items.Add("We can call the multiplication function multiple times by pressing the button and it will return multiple answers");
            listBox1.Items.Add("When the multiplication task is complete, the results will be displayed");
        }

        void BtnRandomClick(object sender, EventArgs e)
        {
            int number = rnd.Next(0, 1000); 
            tbRandomNumber.Text = number.ToString();
        }

        void BtnSlowTaskClick(object sender, EventArgs e)
        {
            a = rnd.Next(1, 9);  // we use global variables to pass data to slow function
            b = rnd.Next(11, 22); // we use global variables to pass data to slow function

            BackgroundWorker bg = new BackgroundWorker();
            bg.DoWork += new DoWorkEventHandler(SlowMultiply);
            bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
            bg.RunWorkerAsync();
        }

        void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            listBox1.Items.Add((++i) + ". Result of multiplication: " + product);
        }

        void SlowMultiply(object sender, DoWorkEventArgs e)
        {
            int prod = a * b;

            for (int i = 1; i <= 5; i++)
            {
                Thread.Sleep(500);
            }

            product = prod.ToString(); // update the global variable
        }       
    }
}

【问题讨论】:

  • 你为什么要BackgroundWorker,使用任务和常用的锁定或联锁方法
  • 我尝试使用任务但没有成功,但这是因为我没有使用它们的经验。你有一些链接我可以看到一个例子吗?或者,也许您可​​以使用任务更改我的代码以实现相同的目标?

标签: c# multithreading winforms backgroundworker


【解决方案1】:

您可以像这样通过后台工作人员发送参数:

int a =  rnd.Next(1, 9);
int b =  rnd.Next(11, 22);
var data = new Tuple<int, int>(a, b);
bg.RunWorkerAsync(argument: data);  

然后在你的工作方法中

void SlowMultiply(object sender, DoWorkEventArgs e)
        {
            var mydata = (Tuple<int, int>) e.Argument;
            int product = mydata.Item1 * mydata.Item2;


            for (int i = 1; i <= 5; i++)
            {
                Thread.Sleep(500);
            }

            product = prod.ToString(); // update the global variable
        }       
    }

另外,您也可以在工作方法中计算随机数。

【讨论】:

  • Thread.Sleep(500) 是否需要 for 循环?相反,我们不能将其更改为 Thread.Sleep(2500) 吗?
  • @SatishPai 那也是一样,但也许 Nick_F 这样做有他自己的理由。
  • 当然没有必要为那个延迟使用循环。原则上更新应用程序状态栏中的 ProgressBar 可能很有用。此外,当我可以让事情变得复杂时,为什么要让事情变得简单呢? :)
  • 谢谢汤姆,这正是我想要的。
猜你喜欢
  • 1970-01-01
  • 2019-08-01
  • 1970-01-01
  • 2013-12-19
  • 1970-01-01
  • 2012-12-19
  • 2010-12-22
  • 2011-03-24
  • 1970-01-01
相关资源
最近更新 更多