BlockingCollection worker 需要通过匿名函数 return 一个值
BlockingCollection worker needs to return a value via anonymous function
我遇到了一个棘手的情况,想知道是否有人可以阐明这件事:
我有一个这样调用的阻塞收集操作工作器
ultraHash hash = new ultraHash(lblFolder.Text, (Action) (() => {
textBox1.Text = self.getMD5();
});
runQueue.addAction(hash);
现在 "self" 有伪代码,这就是为什么,这是 worker
(其中 runQueue
是 BlockingCollection
容器 class)
class ultraHash
{
string _filePath;
Action _onComplete;
string _md5;
public ultraHash(string filePath)
{
_filePath = filePath;
}
public ultraHash(string filePath, Action onComplete) : this(filePath) //constructor chaining
{
_onComplete = onComplete;
}
public override void action()
{
using (var md5 = MD5.Create())
{
try
{
using (var stream = File.OpenRead(_filePath))
{
_md5 = MakeHashString(md5.ComputeHash(stream));
if (_onComplete != null) _onComplete();
}
}
catch (IOException)
{
/***
* file is Busy
*/
}
}
}
public string getMD5()
{
return _md5;
}
private string MakeHashString(byte[] hashBytes)
{
StringBuilder hash = new StringBuilder(32);
foreach (byte b in hashBytes)
{
hash.Append(b.ToString("X2").ToLower());
}
return hashBytes.ToString();
}
}
现在我想要发生的是在第一个片段中的匿名方法 Action (() => {}
在队列完成后执行 并且 能够包含 MD5 总和.我知道这里存在线程安全问题,所以我知道我必须 invoke
返回到 textBox1
所在的父线程,但目前我只是不知道如何做到这一点(是甚至有可能吗?)
编辑
我通常不会 "edit" 回答,但如果其他人遇到这个问题,这是我最终使用的代码,感谢 usr
的回答。注意 BeginInvoke
ultraHash hash = null;
hash = new ultraHash(lblFolder.Text, (Action) (() => {
this.BeginInvoke((Action) (() => {
txtMain.Text = hash.getMD5();
}));
}));
runQueue.addAction(hash);
此外,如果您想知道我为什么这样做,那只是为了让我可以 "watch" 一个文件夹来存放任何文件更改,然后存储元数据更改,因为整个文件夹都可以拖动 in/out 在 FIFO 队列中需要有一个排队机制,父文件夹也被散列,所以任何文件更改都需要冒泡,最后可能是文件在尝试散列时被锁定在这种情况下先进先出队列可以等待
您可能应该将散列作为参数传递给 onComplete
函数。 getMD5
不需要存在。
如果你坚持这样做,你需要一点初始化舞蹈:
ultraHash hash = null;
hash = new ultraHash(lblFolder.Text, (Action) (() => {
textBox1.Text = hash.getMD5();
});
ultraHash
的整个设计看起来很奇怪。 class 真的有必要存在吗?计算散列的单个静态方法应该足够了。
我遇到了一个棘手的情况,想知道是否有人可以阐明这件事:
我有一个这样调用的阻塞收集操作工作器
ultraHash hash = new ultraHash(lblFolder.Text, (Action) (() => {
textBox1.Text = self.getMD5();
});
runQueue.addAction(hash);
现在 "self" 有伪代码,这就是为什么,这是 worker
(其中 runQueue
是 BlockingCollection
容器 class)
class ultraHash
{
string _filePath;
Action _onComplete;
string _md5;
public ultraHash(string filePath)
{
_filePath = filePath;
}
public ultraHash(string filePath, Action onComplete) : this(filePath) //constructor chaining
{
_onComplete = onComplete;
}
public override void action()
{
using (var md5 = MD5.Create())
{
try
{
using (var stream = File.OpenRead(_filePath))
{
_md5 = MakeHashString(md5.ComputeHash(stream));
if (_onComplete != null) _onComplete();
}
}
catch (IOException)
{
/***
* file is Busy
*/
}
}
}
public string getMD5()
{
return _md5;
}
private string MakeHashString(byte[] hashBytes)
{
StringBuilder hash = new StringBuilder(32);
foreach (byte b in hashBytes)
{
hash.Append(b.ToString("X2").ToLower());
}
return hashBytes.ToString();
}
}
现在我想要发生的是在第一个片段中的匿名方法 Action (() => {}
在队列完成后执行 并且 能够包含 MD5 总和.我知道这里存在线程安全问题,所以我知道我必须 invoke
返回到 textBox1
所在的父线程,但目前我只是不知道如何做到这一点(是甚至有可能吗?)
编辑
我通常不会 "edit" 回答,但如果其他人遇到这个问题,这是我最终使用的代码,感谢 usr
的回答。注意 BeginInvoke
ultraHash hash = null;
hash = new ultraHash(lblFolder.Text, (Action) (() => {
this.BeginInvoke((Action) (() => {
txtMain.Text = hash.getMD5();
}));
}));
runQueue.addAction(hash);
此外,如果您想知道我为什么这样做,那只是为了让我可以 "watch" 一个文件夹来存放任何文件更改,然后存储元数据更改,因为整个文件夹都可以拖动 in/out 在 FIFO 队列中需要有一个排队机制,父文件夹也被散列,所以任何文件更改都需要冒泡,最后可能是文件在尝试散列时被锁定在这种情况下先进先出队列可以等待
您可能应该将散列作为参数传递给 onComplete
函数。 getMD5
不需要存在。
如果你坚持这样做,你需要一点初始化舞蹈:
ultraHash hash = null;
hash = new ultraHash(lblFolder.Text, (Action) (() => {
textBox1.Text = hash.getMD5();
});
ultraHash
的整个设计看起来很奇怪。 class 真的有必要存在吗?计算散列的单个静态方法应该足够了。