C# 事件和线程

标签 c# .net events

示例程序:监听某个文件夹上的文件系统事件,并在计时器事件触发时将文件系统事件信息打印到控制台。

class Program
{
    public static string location = @"D:\TestEvents";
    public static double interval = 15000; 

    public static System.Timers.Timer timer;
    public static List<string> listOfChanges = new List<string>();

    static void Main(string[] args)
    {
        StartWatch();
        StartTimer();

        Console.ReadLine();
    }

    private static void StartWatch()
    {
        FileSystemWatcher Watcher = new FileSystemWatcher();
        Watcher.Path = location;
        Watcher.Created += new FileSystemEventHandler(OnFileCreatedOrDeleted);
        Watcher.Deleted += new FileSystemEventHandler(OnFileCreatedOrDeleted);
        Watcher.EnableRaisingEvents = true;
    }

    static void OnFileCreatedOrDeleted(object sender, FileSystemEventArgs e)
    {
        listOfChanges.Add(String.Format("Change Type: {0}, Name: {1}, Time: {2}", e.ChangeType, e.Name, DateTime.Now));
    }

    private static void StartTimer()
    {
        timer = new System.Timers.Timer();
        timer.AutoReset = false;
        timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerEpleased);
        timer.Interval = interval;
        timer.Start();
    }

    private static void OnTimerEpleased(object sender, System.Timers.ElapsedEventArgs e)
    {
        Console.WriteLine("Timer event fired: " + DateTime.Now);
        foreach (var item in listOfChanges)
        {
            Console.WriteLine(item);
        }
        Console.WriteLine();
        listOfChanges.Clear();

        timer.Interval = interval;
        timer.Start();
    }
}

访问相同的存储静态List<string> listOfChanges是否安全来自两个事件处理程序? 我真的不明白事件的底层是如何运作的。它是否创建一些全局事件处理程序队列并一一运行所有事件处理程序,无论事件类型如何?或者它为每个事件处理程序类型创建不同的线程?

编辑: 我想最好的解决方案是使用 BlockingCollectionConcurrentQueue ,所以应该是这样的:

public static BlockingCollection<string> listOfChanges = new BlockingCollection<string>();

static void OnFileCreatedOrDeleted(object sender, FileSystemEventArgs e)
{
    listOfChanges.Add(String.Format("Change Type: {0}, Name: {1}, Time: {2}", e.ChangeType, e.Name, DateTime.Now));
}

private static void OnTimerEpleased(object sender, System.Timers.ElapsedEventArgs e)
{
    Console.WriteLine("Timer event fired: " + DateTime.Now);
    while (listOfChanges.Count > 0)
    {
        string item;
        bool b = listOfChanges.TryTake(out item);
        if (b)
        {
            Console.WriteLine(item);
        }
    }
    Console.WriteLine();

    timer.Interval = interval;
    timer.Start();
}

最佳答案

通用列表不是线程安全的。当遍历 listOfChanges 时(在 OnTimerEpleased 中),您可能会收到错误,并且新条目将向列表中添加条目(OnFileCreatedOrDeleted)。请参阅http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx 。要么同步对列表的访问,要么使用内置的线程安全集合:http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx

关于C# 事件和线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13739697/

相关文章:

c# - 如何将报告转换为图像?

Ruby - 主线程退出时不要终止进程

wpf - 在 WPF 中存储事件处理程序方法的位置 - MVVM

c# - 获取 "type or namespace name could not be found"但一切似乎都正常?

.net - 为什么第一个 WCF 客户端调用很慢?

c# - JSON 字符串在 JSON.parse 中失败,但通过了 JsonConvert.DeserializeObject

c# - 如何序列化 DevExpress XtraReport 报告设计

c# - 当用户控件卸载时从 ViewModel 中删除事件

c# - session 不持久?

c# - 在当前HttpContext session 中设置新的access_token