Запуск потока с двумя параметрами
У меня есть метод, который вызывается на событие, которое представляет мне две переменные varA, varB (обе строки). Этот метод вызывается с новой информацией довольно часто, поэтому я создал отдельный метод, который принимает два параметра. Я хочу запустить этот метод в потоке, однако ударил вопрос, что поток.Start не будет принимать параметры.
Я попробовал несколько предполагаемых методов, но до сих пор не имел успеха.. Я думаю, что мой лучший выбор-создать отдельный класс, и разберись с этим там.. Однако у меня есть список, в который я вставляю данные, и попал в тупик, когда отдельный класс попытался получить доступ к этому списку, так как он был в другом классе.
Кто-нибудь может мне помочь, пожалуйста?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 Listpublic 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-это метод, который вы хотите запустить, и параметры извлекаются оттуда, где это необходимо.