在c#中有没有办法将对象放在另一个线程中?我发现的是如何在另一个线程中实际执行某些方法。我真正想要做的是在新线程中实例化一个对象,以便以后使用它提供的方法。
希望你能帮助我, 俄
答案 0 :(得分:25)
对象实际上不属于某个线程。如果您有对象的引用,则可以从许多线程访问它。
这可能会给对象带来问题,这些对象不是从许多线程访问的,比如(几乎所有)System.Windows.Forms类,以及对COM对象的访问。
如果您只想从同一个线程访问对象,请在对象(或包装对象)中存储对线程的引用,并通过该线程执行方法。
答案 1 :(得分:15)
关于线程如何在这里工作似乎有些混乱,所以这是一个入门(非常简短,所以在进一步尝试多线程编程之前你应该找到更多的材料。)
对象和内存本质上是多线程的,因为进程中的所有线程都可以在选择时访问它们。
所以对象与线程没有任何关系。
但是,代码在一个线程中执行,它是代码执行的线程,你可能正在执行。
不幸的是,没有办法只是“将对象放入不同的线程”,你需要专门启动一个线程并指定在该线程中执行的代码。因此,该代码使用的对象可以“说”属于该线程,尽管这是您自己强加的人为限制。
所以没有办法做到这一点:
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中执行。使方法在原始线程中执行的唯一方法是与原始线程协作并“请求它”执行该方法。你如何做到这一点取决于具体情况,有很多方法可以做到这一点。
总结一下你想要的:你想创建一个新线程,并在该线程中执行代码。
要做到这一点,请查看.NET的Thread类。
但请注意:多线程应用程序非常难以正确使用,我不会为程序添加多线程功能,除非:
答案 2 :(得分:8)
进程的所有线程共享相同的数据(忽略线程本地存储),因此不需要在线程之间显式迁移对象。
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();
}
}
答案 3 :(得分:2)
所有线程都可以看到堆栈 堆,所以如果线程有你需要的对象的引用(例如通过方法传入),那么线程可以使用那些对象。这就是为什么在多线程时必须非常小心地访问对象,因为两个线程可能会尝试同时更改对象。
.NET中有一个ThreadLocal<T>
类可用于将变量限制为特定线程:请参阅http://msdn.microsoft.com/en-us/library/dd642243.aspx和http://www.c-sharpcorner.com/UploadFile/ddoedens/UseThreadLocals11212005053901AM/UseThreadLocals.aspx
答案 4 :(得分:1)
使用ParameterizedThreadStart
将对象传递给您的主题。
答案 5 :(得分:0)
“供以后使用它提供的方法。”
使用包含在新线程和其他数据和方法上执行的方法的类,您可以从线程获取新线程中的数据和方法的访问权。
但是......如果你从类中执行一个方法,那么你正在当前的线程上执行。
要在新线程上执行该方法,需要一些线程同步。
System.Windows.Forms.Control.BeginInvoke这样做,Control线程一直等到请求到来。
WaitHandle 课程可以帮到你。
答案 6 :(得分:0)
很抱歉重复一些以前的工作,但OP说
我真正想要做的是在新线程中实例化一个对象,以便以后使用它提供的方法。
让我将其解释为:
我真正想做的是让一个新线程实例化一个对象,以便以后我可以使用该对象的方法。
如果我错过了标记,请为我纠正。这是一个例子:
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.";
}}}}
答案 7 :(得分:0)
就像详细说明以前的答案一样。为了回到问题,所有线程共享对象和内存空间。所以它们总是被共享,但我假设您希望安全地这样做,并使用另一个线程创建的结果。
首先尝试一种可信的C#模式。 Async Patterns 有一些设置模式可以在线程之间传输基本消息和数据。 通常,一个威胁在计算结果后就完成了!
生命威胁:在异步和共享生命威胁数据时,没有什么是万无一失的。 因此,如果您确实需要走这条路线并尝试遵循已知的模式,那么基本上要尽可能简单。
所以现在我想详细说明为什么一些已知的模式具有某种结构:
Eventargs:在传递对象之前创建对象的深层复制。 (这不是万无一失的,因为某些引用可能仍然是共享的。) 使用基本类型(如int浮点数等)传递结果。这些可以在构造函数上创建并使其成为不可变的。
原子关键词这些类型,或创建监视器等。坚持一个线程读取其他写入。
假设您有复杂的数据,您希望同时在两个线程上使用一种完全不同的方法来解决这个问题,我还没有测试过: 您可以将结果存储在数据库中,让其他可执行文件读取它。 (在行级别上会出现锁定,但您可以再次尝试或更改SQL代码,至少会报告可以通过良好设计解决的死锁,而不仅仅是挂起软件!)我只会这样做,如果它实际上是由于其他原因将数据存储在数据库中的意义。
另一种有用的方法是编写F#。默认情况下,对象和所有类型都是不可变的/所以你想要共享的对象应该有一个构造函数,没有方法允许对象被更改或基本类型增加。 所以你创建它们然后它们不会改变!所以在那之后它们是不可变的。 锁定它们并使它们平行工作变得更加容易。不要在C#类中疯狂,因为其他人可能会遵循这个“约定”,而大多数事情如Lists只是在C#中不是不可变的(readonly与immutable不同,const是非常有限的)。 Immutable versus readonly
答案 8 :(得分:-1)
如果您在线程中运行的方法驻留在自定义类中,则可以让此类的成员保存参数。
public class Foo
{
object parameter1;
object parameter2;
public void ThreadMethod()
{
...
}
}