Как назвать метод в потоке с аргументами и возвратить некоторое значение

Мне нравится называть метод в потоке с аргументами и возвращать некоторое значение здесь пример

class Program
{
    static void Main()
    {
        Thread FirstThread = new Thread(new ThreadStart(Fun1));
        Thread SecondThread = new Thread(new ThreadStart(Fun2));
        FirstThread.Start();
        SecondThread.Start();
    }
    public static void Fun1()
    {
        for (int i = 1; i <= 1000; i++)
        {
            Console.WriteLine("Fun1 writes:{0}", i);
        }
    }
    public static void Fun2()
    {
        for (int i = 1000; i >= 6; i--)
        {
            Console.WriteLine("Fun2 writes:{0}", i);
        }
    }
}

Я знаю это выше примера, выполненного успешно, но если метод fun1 как это

public int fun1(int i,int j)
{
    int k;
    k=i+j;
    return k;
}

затем, как я могу назвать это в потоке?

6
задан Cœur 10 October 2018 в 07:23
поделиться

6 ответов

Это может быть другой подход. Здесь ввод передается как параметризованный поток, а тип возвращаемого значения передается в событии делегата, так что, когда поток завершится, он вызовет делегат. Это будет нормально, чтобы получить результат, когда поток завершится.

 public class ThreadObject
    {
        public int i;
        public int j;
        public int result;
        public string Name;
    }



    public delegate void ResultDelegate(ThreadObject threadObject);

    public partial class Form1 : Form
    {

        public event ResultDelegate resultDelete;

        public Form1()
        {
            InitializeComponent();

            resultDelete += new ResultDelegate(resultValue);
        }

        void resultValue(ThreadObject threadObject)
        {
            MessageBox.Show("Thread Name : " + threadObject.Name + " Thread Value : " + threadObject.result);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ThreadObject firstThreadObject = new ThreadObject();
            firstThreadObject.i = 0;
            firstThreadObject.j = 100;
            firstThreadObject.Name = "First Thread";

            Thread firstThread = new Thread(Fun);
            firstThread.Start(firstThreadObject);


            ThreadObject secondThreadObject = new ThreadObject();
            secondThreadObject.i = 0;
            secondThreadObject.j = 200;
            secondThreadObject.Name = "Second Thread";

            Thread secondThread = new Thread(Fun);
            secondThread.Start(secondThreadObject);

        }


        private void Fun(object parameter)
        {
            ThreadObject threadObject = parameter as ThreadObject;

            for (; threadObject.i < threadObject.j; threadObject.i++)
            {
                threadObject.result += threadObject.i;

                Thread.Sleep(10);
            }

            resultValue(threadObject);
        }
    }
7
ответ дан 8 December 2019 в 02:21
поделиться

Для некоторых альтернатив; currying:

static ThreadStart CurryForFun(int i, int j)
{ // also needs a target object if Fun1 not static
    return () => Fun1(i, j);
}

Thread FirstThread = new Thread(CurryForFun(5, 12));

или напишите свой собственный тип захвата (это в целом сопоставимо с тем, что компилятор делает для вас, когда вы используете анонимные методы / лямбда-выражения с захваченными переменными, но было реализовано иначе):

class MyCaptureClass
{
    private readonly int i, j;
    int? result;
    // only available after execution
    public int Result { get { return result.Value; } }
    public MyCaptureClass(int i, int j)
    {
        this.i = i;
        this.j = j;
    }
    public void Invoke()
    { // will also need a target object if Fun1 isn't static
        result = Fun1(i, j);
    }
}
...
MyCaptureClass capture = new MyCaptureClass(5, 12);
Thread FirstThread = new Thread(capture.Invoke);
// then in the future, access capture.Result
0
ответ дан 8 December 2019 в 02:21
поделиться

Вы можете использовать перегрузку ParameterizedThreadStart в конструкторе Thread. Он позволяет вам передавать объект в качестве параметра методу потока. Это будет единственный параметр объекта, поэтому я обычно создаю класс параметров для таких потоков. Этот объект также может хранить результат выполнения потока, который вы можете прочитать после завершения потока.

Не забывайте, что доступ к этому объекту во время работы потока возможен, но не является «потокобезопасным». Вы знаете, что делать :)

Вот пример:

void Main()
{
    var thread = new Thread(Fun);
    var obj = new ThreadObject
    {
        i = 1,
        j = 15,
    };

    thread.Start(obj);
    thread.Join();
    Console.WriteLine(obj.result);
}

public static void Fun(Object obj)
{
    var threadObj = obj as ThreadObject;
    threadObj.result = threadObj.i + threadObj.j;
}

public class ThreadObject
{
    public int i;
    public int j;
    public int result;
}
0
ответ дан 8 December 2019 в 02:21
поделиться

попробуйте backgroundWorker http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx вы можете передать значение событию DoWork с помощью DoWorkEventArgs и получить значение в RunWorkerCompleted.

0
ответ дан 8 December 2019 в 02:21
поделиться

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

// Create function delegate (it can be any delegate)
var FunFunc = new Func<int, int, int>(fun1);
// Start executing function on thread pool with parameters
IAsyncResult FunFuncResult = FunFunc.BeginInvoke(1, 5, null, null);
// Do some stuff
// Wait for asynchronous call completion and get result
int Result = FunFunc.EndInvoke(FunFuncResult);

Эта функция будет выполняться в потоке пула потоков, и эта логика полностью прозрачна для ваше приложение. В общем, я предлагаю выполнять такие небольшие задачи в пуле потоков, а не в выделенном потоке.

1
ответ дан 8 December 2019 в 02:21
поделиться

Вы должны быть в состоянии использовать анонимный метод или лямбду для обеспечения полной статической проверки:

Thread FirstThread = new Thread(() => Fun1(5, 12));

или если вы хотите что-то сделать с результатом:

Thread FirstThread = new Thread(() => {
    int i = Fun1(5, 12);
    // do something with i
});

но обратите внимание, что это "что-то сделать" по-прежнему выполняется в контексте нового потока (но с доступом к другим переменным во внешнем методе (Main) благодаря "захваченным переменным").

Если у вас C# 2.0 (и не выше), то:

Thread FirstThread = new Thread((ThreadStart)delegate { Fun1(5, 12); });

и

Thread FirstThread = new Thread((ThreadStart)delegate {
    int i = Fun1(5, 12);
    // do something with i
});
24
ответ дан 8 December 2019 в 02:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: