我正在使用FileSystemWatcher
来抓住文件夹中任何文件的每个created
,changed
,deleted
和renamed
更改。
通过这些更改,我需要对这些文件的内容执行简单的校验和。简单地说,我正在打开一个文件流并将其传递给MD5类:
private byte[] calculateChecksum(string frl)
{
using (FileStream stream = File.Open(frl, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return this.md5.ComputeHash(stream);
}
}
问题在于我需要处理的文件数量。例如,假设我在文件夹中创建了200个文件,然后将所有文件复制并粘贴到同一文件夹中。此操作将导致200个事件和200个calculateChecksum()
执行。
我怎么能解决这类问题?
答案 0 :(得分:2)
在from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput
from kivy.properties import ListProperty, StringProperty
import re
from kivy.lang import Builder
Builder.load_string('''
<Intro>:
BoxLayout:
Button:
text: 'Press to go to SecondScreen'
font_size: '20px'
on_release: root.manager.current = 'SecondScreen'
<SecondScreen>:
ComboLayout:
Label:
text: "working?"
font_size: '20px'
ComboEdit:
size_hint: .5, .5
pos_hint: {'center':(.5, .5)}
font_size: '100px'
multiline: False
''')
class ComboEdit(TextInput):
options = ListProperty([])
def __init__(self, **kw):
super(ComboEdit, self).__init__(**kw)
self.ddn = DropDown()
self.ddn.bind(on_select=self.on_select)
def on_options(self, instance, value):
for option in value:
but = Button(text=option,
size_hint_y=None,
height='36sp',
on_release=lambda btn: self.ddn.select(btn.text))
self.ddn.add_widget(but)
def on_select(self, instance, value):
self.text = value
def on_text(self, instance, value):
self.options = [str(i) for i in range(0,8)]
if not self.get_root_window():
return # do proceed if I'm not displayed <=> If have no parent
self.ddn.open(self)
class ComboLayout(BoxLayout):
pass
class Intro(Screen):
pass
class SecondScreen(Screen):
pass
class BugDemoApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(Intro(name='Intro'))
sm.add_widget(SecondScreen(name='SecondScreen'))
return sm
if __name__ == '__main__':
BugDemoApp().run()
处理程序中,将任务放入将由某个worker处理的队列。工作人员可以以目标速度或/和频率处理校验和计算任务。可能一个工人会更好,因为许多读者可以通过许多阅读寻求减慢硬盘。
尝试阅读有关BlockingCollection的信息: https://msdn.microsoft.com/ru-ru/library/dd997371(v=vs.110).aspx
和生产者 - 消费者数据流模式 https://msdn.microsoft.com/ru-ru/library/hh228601(v=vs.110).aspx
FileSystemWatcher
//在FileSystemWatcher处理程序内部
var workerCount = 2;
BlockingCollection<String>[] filesQueues= new BlockingCollection<String>[workerCount];
for(int i = 0; i < workerCount; i++)
{
filesQueues[i] = new BlockingCollection<String>(500);
// Worker
Task.Run(() =>
{
while (!filesQueues[i].IsCompleted)
{
string url;
try
{
url= filesQueues[i].Take();
}
catch (InvalidOperationException) { }
if (!string.IsNullOrWhiteSpace(url))
{
calculateChecksum(url);
}
}
}
}
此外,您可以创建多个消费者,只需同时调用Take或TryTake - 每个项目仅由单个消费者使用。但考虑到在这种情况下,许多工作人员可以处理一个文件,而多个硬盘读取器可以减慢硬盘驱动器。
在多个工作人员的情况下UPD,最好进行多个BlockingCollections,并使用索引推送队列中的文件:
答案 1 :(得分:0)
我已经设置了一个 cosumer-producer 模式来解决这个问题,我尝试使用一个线程池来平滑大量的工作,共享一个{ {1}}
BlockingCollection&amp;线程池强>:
BlockingCollection
正如你所看到的,我已经创建了一个I treadPool设置并发为4.因此,无论是否有private BlockingCollection<Index.ResourceIndexDocument> documents;
this.pool = new SmartThreadPool(SmartThreadPool.DefaultIdleTimeout, 4);
this.documents = new BlockingCollection<string>();
工作,都会同时只有4个线程工作。在游泳池中处理的单位。
<强>生产者强>:
x > 4
<强>消费强>:
public void warn(string channel, string frl)
{
this.pool.QueueWorkItem<string, string>(
(file) => this.files.Add(file),
channel,
frl
);
}