есть ли какой-либо путь в c# для помещения объектов в другой поток? Все, что я нашел, - то, как на самом деле выполнить некоторые методы в другом потоке. То, что я на самом деле хочу сделать, является к instanciate объектом в новом потоке для более позднего использования методов, которые это предоставляет.
Надежда можно помочь мне, Russo
На самом деле объекты не принадлежат потоку. Если у вас есть ссылка на объект, вы можете получить к нему доступ из многих потоков.
Это может вызвать проблемы с объектами, которые не предназначены для доступа из многих потоков, таких как (почти все) классы System.Windows.Forms, и доступ к COM-объектам.
Если вы хотите получить доступ к объекту только из того же потока, сохраните ссылку на поток в объекте (или объекте-оболочке) и выполните методы через этот поток.
Похоже, что существует некоторая путаница в том, как работают потоки, так что это учебник (очень короткий, так что вам следует найти больше материала, прежде чем углубляться в многопоточное программирование).
Объекты и память по своей природе многопоточны в том смысле, что все потоки в процессе могут обращаться к ним по своему усмотрению.
Таким образом, объекты не имеют ничего общего с потоками.
Однако код выполняется в потоке, и вам, вероятно, нужен именно поток, в котором выполняется код.
К сожалению, не существует способа просто "поместить объект в другой поток", как вы выразились, вам нужно специально запустить поток и указать, какой код должен выполняться в этом потоке. Таким образом, можно "сказать", что объекты, используемые этим кодом, принадлежат этому потоку, хотя это искусственное ограничение, которое вы сами себе навязываете.
Так что нет никакого способа сделать это:
SomeObject obj = new SomeObject();
obj.PutInThread(thatOtherThread);
obj.Method(); // this now executes in that other thread
На самом деле, распространенная ловушка, в которую попадают многие начинающие многопоточные программисты, заключается в том, что если они создают объект в одном потоке, а вызывают методы на нем из другого потока, то все эти методы выполняются в потоке, который создал объект. Это неверно, методы всегда выполняются в том потоке, который их вызвал.
Поэтому следующее также неверно:
Thread 1:
SomeObject obj = new SomeObject();
Thread 2:
obj.Method(); // executes in Thread 1
Метод здесь будет выполняться в потоке 2. Единственный способ заставить метод выполняться в исходном потоке - это сотрудничать с исходным потоком и "попросить" его выполнить этот метод. Как это сделать, зависит от ситуации, и существует множество способов сделать это.
Итак, подытожим то, что вы хотите: Вы хотите создать новый поток и выполнить код в этом потоке.
Чтобы сделать это, посмотрите на класс Thread в .NET.
Но будьте осторожны: Многопоточные приложения очень трудно сделать правильными, я бы не стал добавлять возможности многопоточности в программу, если только:
Все потоки процесса используют одни и те же данные (игнорируя локальное хранилище потока), поэтому нет необходимости явно переносить объекты между потоками.
internal sealed class Foo
{
private Object bar = null;
private void CreateBarOnNewThread()
{
var thread = new Thread(this.CreateBar);
thread.Start();
// Do other stuff while the new thread
// creates our bar.
Console.WriteLine("Doing crazy stuff.");
// Wait for the other thread to finish.
thread.Join();
// Use this.bar here...
}
private void CreateBar()
{
// Creating a bar takes a long time.
Thread.Sleep(1000);
this.bar = new Object();
}
}
Все потоки могут видеть стек кучу , поэтому, если у потока есть ссылка на нужные вам объекты (например, переданная через метод), поток может использовать эти объекты. Вот почему вы должны быть очень осторожны при доступе к объектам при многопоточности, так как два потока могут попытаться изменить объект одновременно.
В .NET есть класс ThreadLocal
, который можно использовать для ограничения переменных определенным потоком: см. http://msdn.microsoft.com/en-us/ library / dd642243.aspx и http://www.c-sharpcorner.com/UploadFile/ddoedens/UseThreadLocals11212005053901AM/UseThreadLocals.aspx
"для дальнейшего использования методов, которые он предоставляет."
Используя класс, который содержит метод для выполнения в новом потоке и другие данные и методы, вы можете получить доступ из вашего потока к данным и методам из нового потока.
Но ... если вы выполняете метод из класс, который вы выполняете в текущем потоке.
Для выполнения метода в новом потоке требуется некоторая синхронизация потока.
System.Windows.Forms.Control.BeginInvoke сделайте это, поток управления ждет, пока не поступит запрос .
Класс WaitHandle может вам помочь.
Если метод, который вы запускаете в потоке, находится в пользовательском классе, вы можете иметь члены этого класса для хранения параметров.
public class Foo
{
object parameter1;
object parameter2;
public void ThreadMethod()
{
...
}
}
Используйте ParameterizedThreadStart
, чтобы передать объект вашему потоку.
Извините, что дублирую предыдущую работу, но ОП сказал
Что я на самом деле хочу сделать, так это инстанцировать объект в новом потоке для последующего использования методов, которые он предоставляет.
Позвольте мне интерпретировать это как:
На самом деле я хочу сделать так, чтобы новый поток инстанцировал объект, чтобы позже я мог использовать методы этого объекта.
Пожалуйста, поправьте меня, если я что-то не понял. Вот пример:
namespace silly
{
public static class Program
{
//declared volatile to make sure the object is in a consistent state
//between thread usages -- For thread safety.
public static volatile Object_w_Methods _method_provider = null;
static void Main(string[] args)
{
//right now, _method_provider is null.
System.Threading.Thread _creator_thread = new System.Threading.Thread(
new System.Threading.ThreadStart(Create_Object));
_creator_thread.Name = "Thread for creation of object";
_creator_thread.Start();
//here I can do other work while _method_provider is created.
System.Threading.Thread.Sleep(256);
_creator_thread.Join();
//by now, the other thread has created the _method_provider
//so we can use his methods in this thread, and any other thread!
System.Console.WriteLine("I got the name!! It is: `" +
_method_provider.Get_Name(1) + "'");
System.Console.WriteLine("Press any key to exit...");
System.Console.ReadKey(true);
}
static void Create_Object()
{
System.Threading.Thread.Sleep(512);
_method_provider = new Object_w_Methods();
}
}
public class Object_w_Methods
{
//Synchronize because it will probably be used by multiple threads,
//even though the current implementation is thread safe.
[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
public string Get_Name(int id)
{
switch (id)
{
case 1:
return "one is the name";
case 2:
return "two is the one you want";
default:
return "supply the correct ID.";
}}}}