【发布时间】:2023-03-27 21:06:01
【问题描述】:
我有一个 Windows 服务来处理链表队列中的 xml 文件。队列中的文件是在文件创建时由 FileSystemWatcher 事件添加的。
namespace XMLFTP
{
public class XML_Processor : ServiceBase
{
public string s_folder { get; set; }
public XML_Processor(string folder)
{
s_folder = folder;
}
Thread worker;
FileSystemWatcher watcher;
DirectoryInfo my_Folder;
public static AutoResetEvent ResetEvent { get; set; }
bool running;
public bool Start()
{
my_Folder = new DirectoryInfo(s_folder);
bool success = true;
running = true;
worker = new Thread(new ThreadStart(ServiceLoop));
worker.Start();
// add files to queue by FileSystemWatcher event
return (success);
}
public bool Stop()
{
try
{
running = false;
watcher.EnableRaisingEvents = false;
worker.Join(ServiceSettings.ThreadJoinTimeOut);
}
catch (Exception ex)
{
return (false);
}
return (true);
}
public void ServiceLoop()
{
string fileName;
while (running)
{
Thread.Sleep(2000);
if (ProcessingQueue.Count > 0)
{
// process file and write info to DB.
}
}
}
void watcher_Created(object sender, FileSystemEventArgs e)
{
switch (e.ChangeType)
{
case WatcherChangeTypes.Created:// add files to queue
}
}
}
}
可能存在线程安全问题。
while (running)
{
Thread.Sleep(2000);
if (ProcessingQueue.Count > 0)
{
// process file and write info to DB.
}
}
由于对 ProcessingQueue.Count 的访问不受锁保护,因此如果不同的线程更改“队列”,则 Count 可能会更改。结果,进程文件部分可能会失败。如果您将 Count 属性实现为:
public static int Count
{
get { lock (syncRoot) return _files.Count; }
}
因为锁被提前释放。
我的两个问题:
- 如何使ProcessingQueue.Count正确?
-
如果我使用.NET Framework 4.5 BlockingCollection技能,示例代码为:
class ConsumingEnumerableDemo { // Demonstrates: // BlockingCollection<T>.Add() // BlockingCollection<T>.CompleteAdding() // BlockingCollection<T>.GetConsumingEnumerable() public static void BC_GetConsumingEnumerable() { using (BlockingCollection<int> bc = new BlockingCollection<int>()) { // Kick off a producer task Task.Factory.StartNew(() => { for (int i = 0; i < 10; i++) { bc.Add(i); Thread.Sleep(100); // sleep 100 ms between adds } // Need to do this to keep foreach below from hanging bc.CompleteAdding(); }); // Now consume the blocking collection with foreach. // Use bc.GetConsumingEnumerable() instead of just bc because the // former will block waiting for completion and the latter will // simply take a snapshot of the current state of the underlying collection. foreach (var item in bc.GetConsumingEnumerable()) { Console.WriteLine(item); } } } }
示例使用常量 10 作为迭代子句,如何将队列中的动态计数应用于它?
【问题讨论】:
标签: c# multithreading