Запуск потока с двумя параметрами


У меня есть метод, который вызывается на событие, которое представляет мне две переменные varA, varB (обе строки). Этот метод вызывается с новой информацией довольно часто, поэтому я создал отдельный метод, который принимает два параметра. Я хочу запустить этот метод в потоке, однако ударил вопрос, что поток.Start не будет принимать параметры.

Я попробовал несколько предполагаемых методов, но до сих пор не имел успеха.. Я думаю, что мой лучший выбор-создать отдельный класс, и разберись с этим там.. Однако у меня есть список, в который я вставляю данные, и попал в тупик, когда отдельный класс попытался получить доступ к этому списку, так как он был в другом классе.

Кто-нибудь может мне помочь, пожалуйста?
5 3

5 ответов:

Метод start потока принимает параметр объекта.

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

Нить.Start (Object)

Http://msdn.microsoft.com/en-us/library/system.threading.thread.start.aspx

Обновить

В вашем случае попробуйте вот это,

string varC = varA + "," + varB;
Thread.Start(varC);

И в вашем метод

string args[] = ((string)par).Split(',');

Простое решение...
Это выведет varA, varB на консоль.

new RunTask<string, string>("varA", "varB").StartThread();

public class RunTask<TA, TB>
{
    public TA VarA { get; private set; }
    public TB VarB { get; private set; }

    public RunTask(TA varA, TB varB)
    {
        VarA = varA;
        VarB = varB;
    }
    public void StartThread()
    {
        ThreadPool.QueueUserWorkItem(Worker, this);
    }
    public void Worker(object obj)
    {
        var state = obj as RunTask<TA,TB>;
        Console.WriteLine(state.VarA + ", " + state.VarB);
    }
}

редактировать:
Если вам нужно решение, в котором вам нужно обновить пользовательский интерфейс, это, вероятно, лучшее решение.
И, вероятно, это лучшее решение, чтобы поместить аргументы в отдельный класс, как это.
Вставить код для обновления списка после комментария / / Update List

public class ListForm : Form
{
    private static readonly object _listResultLock = new object();
    private readonly Action<TaskResult> _listResultHandler;

    public ListForm()
    {
        Load += ListForm_Load;
        _listResultHandler = TaskResultHandler;
    }

    private void ListForm_Load(object sender, EventArgs e)
    {
        new RunTask(new Task("varA", "varB", TaskResultHandler)).StartThread();
    }
    public void TaskResultHandler(TaskResult result)
    {
        if (InvokeRequired)
        {
            Invoke(_listResultHandler, result);
            return;
        }
        lock (_listResultLock)
        {
            // Update List
        }
    }
}

public class Task
{
    public Action<TaskResult> Changed { get; private set; }
    public string VarA { get; private set; }
    public string VarB { get; private set; }

    public Task(string varA, string varB, Action<TaskResult> changed)
    {
        VarA = varA;
        VarB = varB;
        Changed = changed;
    }
}
public class TaskResult
{
    public string VarA { get; private set; }
    public string VarB { get; private set; }

    public TaskResult(string varA, string varB)
    {
        VarA = varA;
        VarB = varB;
    }
}
public class RunTask
{
    private readonly Task _task;

    public RunTask(Task task)
    {
        _task = task;
    }
    public void StartThread()
    {
        ThreadPool.QueueUserWorkItem(Worker, _task);
    }
    public void Worker(object obj)
    {
        var state = obj as Task;
        if (state == null) return;
        if (state.Changed == null) return;
        state.Changed(new TaskResult("this is " + state.VarA, "this is " + state.VarA));
    }
}

Если вы знаете, что будет передано потоку, то вы можете передать ему объекты.

Подробнее читайте здесь - > http://msdn.microsoft.com/en-us/library/6x4c42hc.aspx

Пример:

void someFunction()
{
    Thread t = new Thread(doWork);

Затем,

    t.Start(new int[] { 1, 2 }); //two values passed to the thread.

Или,

    t.Start(1); //one value passed to the thread.
}



Итак, метод -

void doWork(object data)
{
    System.Collections.IList list = data as System.Collections.IList;
    if (list != null)
    {
        object[] _objArr = data as object[];
        foreach (object io in list)
        {
            System.Diagnostics.Trace.WriteLine(io);
        }
    }
    else
    {
        System.Diagnostics.Trace.WriteLine(data);
    }
}

Вы можете выполнить метод с параметрами в другом потоке по-разному: через класс потока, через систему.ComponentModel.BackgroundWorker, через ThreadPool. Если метод вызывается часто, я думаю, что ThreadPool подойдет:

        ThreadPool.QueueUserWorkItem(
        (args)=>
            {
                try
                {
                //args - object, you can put in it string[] or
                // whatever you want

                // do work
                }
                catch(Exception e)
                {
                    // dont throw exceptions in this thread
                    // or application will crashed
                }
            }
        );

Вы можете прочитать об этих классах на msdn:

Http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx

Http://msdn.microsoft.com/en-us/library/system.threading.parameterizedthreadstart.aspx

Http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Вместо System.Thread можно использовать делегат.

Например:

public delegate void RunMyMethod(String a, String b);

RunMyMethod myDelegate = new RunMyMethod(MyMethod);
myDelegate.BeginInvoke(someAFromSomeWhere, someBFromSomeWhere);

Где MyMethod-это метод, который вы хотите запустить, и параметры извлекаются оттуда, где это необходимо.