使用 Windows 服务编写同步应用程序以并行处理文件 [英] Writing a sync application using Windows Service to process files in Parallel

查看:23
本文介绍了使用 Windows 服务编写同步应用程序以并行处理文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 Windows 服务器上有一个文件夹,人们将在其中上传 CSV 文件到 C:\Uploads.

I have a folder on my windows server, where people will be uploading CSV files to, C:\Uploads.

我想编写一个简单的 Windows 服务应用程序,它将扫描此上传文件夹(每 5 秒)并收集文件并并行处理它们(线程/每个文件?).但是主扫描过程不能重叠,即需要加锁.

I want to write a simple windows service application that will scan this uploads folder (every 5 seconds) and collect the files in and process them in parallel (Thread /per File?). However, the main scanning process should not overlap, i.e. locking is required.

所以,我是这样试验的:我知道这不是 Windows 服务代码,它是一个测试想法的控制台应用程序...

So, I was experimenting with it like this: I am aware this is not windows service code, it's a console app to test ideas...

更新代码,基于 dcastro 的回复

class Program
{
    static Timer _InternalTimer;
    static Object _SyncLock = new Object();

    static void Main(string[] args)
    {
        _InternalTimer = new Timer(InitProcess, null, 0, 5000); // Sync cycle is every 5 sec

        Console.ReadKey();
    }

    private static void InitProcess(Object state)
    {
        ConsoleLog("Starting Process");
        StartProcess();
    }

    static void StartProcess()
    {
        bool lockTaken = false;
        try
        {
            Monitor.TryEnter(_SyncLock, ref lockTaken);
            if (lockTaken)
            {
                ConsoleLog("Lock Acquired. Doing some dummy work...");

                List<string> fileList = new List<string>()
                {
                    "fileA.csv",
                    "fileB.csv"
                };

                Parallel.ForEach(fileList, (string fileName) =>
                {
                    ConsoleLog("Processing File: " + fileName);
                    Thread.Sleep(10000); // 10 sec to process each file
                });

                GC.Collect();
            }
            else
                ConsoleLog("Sync Is Busy, Skipping Cycle");
        }
        finally
        {
            if (lockTaken)
                Monitor.Exit(_SyncLock);
        }
    }

    static void ConsoleLog(String Message)
    {
        Console.WriteLine("[{0}]: {1}",
            DateTime.UtcNow.ToString("HH:mm:ss tt"),
            Message);
    }
}

运行时是这样的:

这看起来对吗?任何有关改进此问题的帮助/提示将不胜感激.

Does this look right? Any help/tips on improving this will be much appreciated.

推荐答案

对我来说似乎很好,除了您不需要使用 Task.Factory.StartNew 启动任务.System.Threading.Timer 已经在 ThreadPool 上执行您的回调,因此无需再启动另一个也将在线程池上运行的任务.

It seems fine to me, apart from the fact that you don't need to start a task with Task.Factory.StartNew. The System.Threading.Timer already executes your callback on the ThreadPool, so there's no need to launch yet another task that will also be run on the thread pool.

此外,如果您的计时器每 5 秒计时一次,并且您预计需要大约 10 秒来处理文件,那么您的线程将开始排队等待释放锁.这发生在您发布的示例中.

Also, if your timer ticks every 5 seconds, and you expect it to take about 10 secs to process the files, then your threads will begin to queue up waiting for the lock to be released. That happened on the example you posted.

如果是这种情况,我要么将计时器的周期增加到 10 秒以上,要么使用 Monitor.TryEnter 而不是常规的 lock.TryEnter 会尝试获取锁,不管锁是否被获取,都会立即返回.如果该锁当前被另一个线程占用,您只需完全跳过此勾.

If this is the case, I would either increase the timer's period to more than 10 secs, or use Monitor.TryEnter instead of a regular lock. TryEnter will try to acquire the lock, and return immediately regardless of whether or not the lock was taken. If the lock is currently taken by another thread, you just skip this tick entirely.

这篇关于使用 Windows 服务编写同步应用程序以并行处理文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆