Как я могу избежать глобальных переменных в многопоточном приложении - PullRequest
0 голосов
/ 17 ноября 2018

Я сделал простое приложение, которое вызывает медленно выполняющуюся задачу с использованием фоновых рабочих.Я хотел бы иметь возможность передать некоторые аргументы медленной функции и получить результаты, когда задача завершена.Я могу сделать это с помощью глобальных переменных a, b и product.Есть ли лучший способ передать аргументы медленной функции и получить результат?

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

1 Ответ

0 голосов
/ 17 ноября 2018

Вы можете отправить параметры через фонового работника следующим образом:

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

И, альтернативно, вы можете просто вычислить случайные числа внутри вашего рабочего метода.

...