将(结构体的)实例方法传递给 ThreadStart 似乎会更新虚假实例,因为原始实例不受影响
我的问题是将 this.folderFolder
实例方法传递给 ThreadStart
ctor。我使用 dirAssThread 逐步执行它,并观察它正确并完成更新实例数据成员,然后我返回
if (dirAssThread.IsAlive) completeThread(-1); //***ie abort
并发现与我相同的 this
实例的数据成员通过该方法传递给 ThreadStart
向量的值奇迹般地重置为 0!
这是其他功能
using System;
using System.IO;
using System.Threading;
namespace MonitorService
{
struct myStruct
{
long bytesSzMember;
Thread dirAssThread;
private Object thisLock;
private void completeThread(long bytesSzNew)
{
lock (thisLock)
{
if (bytesSzNew == -1)
{
dirAssThread.Abort();
Console.WriteLine("A thread timed out.");
}
else
{
bytesSzMember = bytesSzNew;
Console.WriteLine("A thread update size.");
}
}
}
private void folderFolder()
{
long bytesSzNew = 0;
DirectoryInfo di = new DirectoryInfo("C:\\SomeDir");
DirectoryInfo[] directories = di.GetDirectories("*",SearchOption.AllDirectories);
FileInfo[] files = di.GetFiles("*",SearchOption.AllDirectories);
foreach (FileInfo file in files)
{
bytesSzNew += file.Length;
}
completeThread(bytesSzNew);
}
private void updateSize()
{
thisLock = new Object();
dirAssThread = new Thread(new ThreadStart(this.folderFolder));
dirAssThread.Start();
Thread.Sleep(5000);
if (dirAssThread.IsAlive) completeThread(-1);
}
}
}
My problem is passing the this.folderFolder
instance method to ThreadStart
ctor. I step through it with dirAssThread
and watch it update the instance data member correctly and complete, then I trap back to
if (dirAssThread.IsAlive) completeThread(-1); //***ie abort
and find that the data member of the same this
instance that I passed with the method to the ThreadStart
ctor has miraculously reset itself to 0!
Here are the other functions
using System;
using System.IO;
using System.Threading;
namespace MonitorService
{
struct myStruct
{
long bytesSzMember;
Thread dirAssThread;
private Object thisLock;
private void completeThread(long bytesSzNew)
{
lock (thisLock)
{
if (bytesSzNew == -1)
{
dirAssThread.Abort();
Console.WriteLine("A thread timed out.");
}
else
{
bytesSzMember = bytesSzNew;
Console.WriteLine("A thread update size.");
}
}
}
private void folderFolder()
{
long bytesSzNew = 0;
DirectoryInfo di = new DirectoryInfo("C:\\SomeDir");
DirectoryInfo[] directories = di.GetDirectories("*",SearchOption.AllDirectories);
FileInfo[] files = di.GetFiles("*",SearchOption.AllDirectories);
foreach (FileInfo file in files)
{
bytesSzNew += file.Length;
}
completeThread(bytesSzNew);
}
private void updateSize()
{
thisLock = new Object();
dirAssThread = new Thread(new ThreadStart(this.folderFolder));
dirAssThread.Start();
Thread.Sleep(5000);
if (dirAssThread.IsAlive) completeThread(-1);
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
更新
问题标题更新后,您看到的问题是结构是在引用时复制的。在将委托分配给线程时,您正在传递结构的副本,并且该副本将由线程更新。当您在
completeThread
中进行检查时,它是针对尚未更新的原始版本的。使用类而不是结构。
替代解决方案
我建议使用等待句柄而不是睡眠和线程中止,因为
Thread.Abort
被认为是一种危险的做法,应该避免(在这种情况下很容易)。我提出以下解决方案,它是一个递归版本,不会遵循循环引用(因此实际上不需要中止,如果您不想要超时功能,可以删除代码)。更新
由于我们现在有了循环引用检测,因此可以删除线程和中止代码,因为之前的代码可以在线程处于无限循环时中止线程 - 现在不需要这样做:
Update
After the question title update, the problem you are seeing is that structs are copied on reference. You are passing a copy of your struct when assigning the delegate to the thread, and it is this copy that will be updated by the thread. When you do your check in
completeThread
it is against the original which has not been updated.Use a class instead of a struct.
Alternate Solution
I would suggest using wait handles instead of sleeps and thread aborts, as
Thread.Abort
is considered a dangerous practice and should be avoided (quite easily in this case). I propose the following solution which is a recursive version that will not follow circular references (so there is no need to abort in reality, the code can be removed if you do not want a timeout facility).Update
As we now have circular reference detection, the threading and abort code can be removed as that was previously there to abort the thread if it was in an endless loop - no need for that now:
您在这里遇到的问题是,您将
struct
的方法传递给ThreadStart
构造函数,并导致它创建struct
的副本code> 实例并调用副本上的方法。您的代码正在运行,但它正在更新副本而不是原始实例。尝试将
struct
更改为class
,您应该会看到问题消失。The issue you are having here is that you are passing a method of a
struct
to theThreadStart
constructor and that causes it to make a copy of thestruct
instance and invoke the method on the copy. Your code is running, but it is updating the copy not the original instance.Try changing the
struct
toclass
and you should see the problem go away.这是值(结构)类型的细微差别之一。使用值类型的理由很少——而且在很多情况下它们都会增加开销(而不是像您想象的那样消除它)。
只需将类型声明更改为
class
即可。此外,如果您希望此函数超时,为什么不尝试以下操作(您可以完全消除该类):This is one of the nuances of value (struct) types. There are very few reasons to use a value type - and in a wide variety of cases they add overhead (instead of eliminating it, like you would assume).
Just change the type declaration to
class
. Furthermore, if you want a timeout for this function, why not try the following (you can eliminate the class altogether):