1

我创建了一个 Windows 服务,它会不时检查某个是否存在,如果存在,然后从中读取,将数据发送到服务器并将文件移动到另一个文件夹。一个文件的大小约为 1-3 Mb。

我想我会用System.Threading.Timer这里来检查文件是否存在。你怎么看呢?

还有一个问题。如果正在复制文件,则我的应用程序不得从中读取。它应该等到复制完成。只有在那之后,它必须从中读取并执行其他活动。

所以问题:

1)这是一个正确的决定System.Threading.Timer吗?

2) 我如何检查文件是否被复制并等到它完成?

3)我必须使用多线程吗?

4

5 回答 5

5

我想我会用System.Threading.Timer这里来检查文件是否存在。你怎么看呢?

我想你可能会看一下这个FileSystemWatcher类,它会在创建文件时通知你并引发一个事件,而不是使用一个不断轮询文件是否存在的 Timer。

于 2012-09-25T07:31:47.230 回答
5

计时器非常昂贵。您可以使用FileSystemWatcherWhich 监听文件系统更改通知并在目录或目录中的文件更改时引发事件。

// Create a new FileSystemWatcher and set its properties.
    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = /*path*/
    /* Watch for changes in LastAccess and LastWrite times, and
       the renaming of files or directories. */
    watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
       | NotifyFilters.FileName | NotifyFilters.DirectoryName;
    // Only watch text files.
    watcher.Filter = "*.txt";

    // Add event handlers.
    watcher.Changed += new FileSystemEventHandler(OnChanged);
    watcher.Created += new FileSystemEventHandler(OnChanged);
    watcher.Deleted += new FileSystemEventHandler(OnChanged);
    watcher.Renamed += new RenamedEventHandler(OnRenamed);

    // Begin watching.
    watcher.EnableRaisingEvents = true;

那么这将是OnChanged方法:

    //This method is called when a file is created, changed, or deleted.
    private static void OnChanged(object source, FileSystemEventArgs e)
    {
        //Show that a file has been created, changed, or deleted.
        WatcherChangeTypes wct = e.ChangeType;
        Console.WriteLine("File {0} {1}", e.FullPath, wct.ToString());
    }

参考: http ://devproconnections.com/net-framework/how-build-folder-watcher-service-c

于 2012-09-25T07:32:52.097 回答
1

我使用的常用方法是使用 FileSystemWatcher 监视文件夹(或相关 API,如果不是 .NET 托管),并尝试确保对源/目标文件夹执行的唯一操作是在文件夹之间移动/重命名在同一个物理驱动器上,然后删除。如果要添加文件,请将其打开/写入/刷新/关闭它到目标文件系统驱动器上的临时文件夹,然后才将其移动/重命名为正在监视的文件夹。至关重要的是,临时文件夹与目标文件夹位于同一物理驱动器上,这样它就可以在没有数据副本的情况下移动/重命名。

这在非托管系统上运行良好,没有在 C# 上尝试过,但没有看到任何不正常工作的理由。

其他涉及持续轮询和/或检查文件大小的解决方案充其量只是不方便、不灵活、浪费、混乱和延迟。

多线程 - 在任何远程文件系统上都可能是的。网络文件调用往往会在不可恢复性等方面有很长的超时时间,因此在发出错误/异常之前永远阻止调用者。如果您想完成其他任何事情,您可能应该放弃很多,除非您的用户可以容忍“沙漏应用程序”,窗口变得无响应、消失到后面、变灰并且操作系统提供关闭它们。

哦,还有一件事 - 最好在启动时进行清除。东西随时可能出错,所以在运行时清理临时文件夹等中的任何挥之不去的垃圾。

于 2012-09-25T09:43:52.570 回答
0

我不会使用 FileSystemWatcher 它太脆弱了

FileSystemWatcher 不适用于从 Windows 服务创建的文件

我会将计时器设置为合理的滴答周期,您应该没问题。

一些示例代码

Timer_TicK()
{
 // remove tick event handler

 // do your processing

 // add back tick event handler
}

如果您有大量的处理工作要做,这将防止发生多个滴答事件。在您发现由于性能问题需要使用它之前,我不会使用多线程。

在 C# 中,如果您在文件系统复制文件时尝试读取文件,您将收到异常。您将需要检查该异常或检查文件的属性(大小等)以了解何时完成。

于 2012-09-25T08:07:01.237 回答
0

完整计时器示例,每次间隔发生时我都会启动新线程(您不必这样做,但这是一个很好的做法),它会检查文件是否存在并读取它,如果存在则将其删除:

using System;
using System.ServiceProcess;
using System.Threading;
using System.Timers;
using System.IO;

namespace MyNamespace
{
    public partial class Service1:  ServiceBase
    {
        Thread syncThread = null;
        System.Timers.Timer timer1;
        string filePath = @"C:\myfile.txt";
        int interval = 60000;  // 1 min -- adjust as necessary

        public Service1()
        {
           InitializeComponent();             
        }

        protected override void OnStart(string[] args)
        {
            timer1 = new System.Timers.Timer();
            timer1.Interval = interval;
            timer1.Enabled = true;
            timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed);
            timer1.Start();
        }
        protected override void OnStop()
        {
            syncThread.Abort();
            timer1.Stop();
        }
        protected void timer1_Elapsed(object sender, ElapsedEventArgs e)
        {
            syncThread = new Thread(new ThreadStart(doThread));
            syncThread.Start();
        }
        protected void doThread()
        {
            // whatever you put here, it will
            // run for each timer interval that elapses
            // in a separate thread, and each thread will
            // end when the processing in this function ends

            string fileContent = String.Empty;      

            if (File.Exists(filePath)
            {
                FileStream fs = new FileStream(filePath, FileMode.Open);
                StreamReader sr = new StreamReader(fs);
                fileContent = sr.ReadToEnd();
                sr.Close();
                fs.Close();
            } 

            if (fileContent != String.Empty)
            {
               // File was present... process the content...

               // Then I do this...
               File.Delete();
            }
        } 
    }
}

我运行它没有任何问题。我更喜欢在每个时间间隔启动新线程,这样如果上一次运行尚未完成,它不会导致问题。走这条路,你有控制权,可以决定你的间隔是多少,你的过程并不总是在继续——只是服务。另一条路线,FileSystemWatcher它总是在可能的情况下监视和运行,并且您无法调整时间间隔,就像您可以使用计时器一样,以减少正在进行的事件/进程的数量,例如何时/如果文件是创建,然后快速修改和保存。

我看到的唯一缺点是必须自己检查文件属性,但这些检查很容易进行。如果您File.Delete()像我一样在处理后这样做,您只需File.Exists(filePath)要做,以了解文件是否已重新创建。如果您必须检查修改,您只需检查DateTime lastModifed = File.GetLastWriteTime(filePath)(参见http://www.csharp-examples.net/file-creation-modification-time/)与当前时间 + 您的时间间隔(应该是DateTime lastRun = DateTime.Now.AddMilliseconds(interval))。如果lastRun > lastModified,您将不得不处理它。

于 2016-12-14T02:29:38.030 回答