代码之家  ›  专栏  ›  技术社区  ›  kovac

在C中实现以下长时间运行线程的更好方法#

  •  0
  • kovac  · 技术社区  · 8 年前

    我有一个应用程序,它有一个主线程,可以等待事件(例如,接收目录中的文件)并将该文件发布到API。这部分工作正常。

    另一方面,由于某些原因,主线程可能会丢失一些文件。因此,我设置了一个后台线程,在整个应用程序生命周期中运行,以清理丢失的文件,如下所示:

    public virtual void MissedFileHandler()
    {
         if (_missedFileHandlerThread == null || !_missedFileHandlerThread.IsAlive)
         {
              _missedFileHandlerThread = new Thread(new ThreadStart(ClearMissedFiles));
              _missedFileHandlerThread.IsBackground = true;
              _missedFileHandlerThread.Start();
         }
    }
    
    protected virtual void ClearMissedFiles()
    {
         while (true)
         {
             string[] missedFiles = new string[] { };
             missedFiles = Directory.GetFiles(ConfigurationHelper.applicationRootDirectory, "*.txt", SearchOption.TopDirectoryOnly);
             Parallel.ForEach(missedFiless, (currentMissedFile) =>
             {
                 bool isFileInUse = true;
                 isFileInUse = FileHelper.CheckIfFileInUse(filesInUseCollection, currentMissedFile)
                 if (!isFileInUse)
                 {
                     bool isHttpTransferSuccess = false;
                     isHttpTransferSuccess = FileHelper.SendFileToApi(userid, currentMissedFile);
                 if (isHttpTransferSuccess)
                 {
                      File.Delete(currentMissedFile);
    
                 }
             }
         });
         Thread.Sleep(1000);
         }
      }
    

    请注意,由于其他一些原因,不能将其作为Windows服务或计划程序运行。所以,我确实需要一个后台工作人员定期清理丢失的文件。我退房了 Timer WaitHandles 但我不太确定如何使用这些实现以下内容。

    这两个进程(新文件的主偶数处理程序和后台清理程序)的调用方式是,在主应用程序线程中,我将实例化该类并在应用程序启动时调用这些方法 Thread.Sleep() 以及 while (true) 这让我很困扰,我正在寻找更好的方法。谢谢

    2 回复  |  直到 8 年前
        1
  •  3
  •   burnttoast11 Lazy Badger    8 年前

    您可以使用文件监视程序来检测该目录中的新文件。

    private void watch()
    {
      FileSystemWatcher watcher = new FileSystemWatcher();
    
      // Set your path with this
      watcher.Path = path;
    
      // Subscribe to event
      watcher.Changed += new FileSystemEventHandler(OnChanged);
      watcher.EnableRaisingEvents = true;
    }
    
        2
  •  1
  •   Enigmativity    8 年前

    尝试使用Microsoft的反应式框架。然后您可以执行以下操作:

    IObservable<Unit> fileChanges =
        Observable
            .Using(() =>
            {
                var fsw = new FileSystemWatcher();
                fsw.Path = path;
                fsw.EnableRaisingEvents = true;
                return fsw;
            }, fsw =>
                Observable
                    .FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
                        h => fsw.Changed += h,
                        h => fsw.Changed -= h))
            .Select(ep => Unit.Default);
    
    IObservable<Unit> periodically =
        Observable
            .Interval(TimeSpan.FromSeconds(30.0))
            .Select(x => Unit.Default);
    
    IObservable<string> clearMissedFiles =
        fileChanges
            .Merge(periodically)
            .SelectMany(u => Directory.GetFiles(ConfigurationHelper.applicationRootDirectory, "*.txt", SearchOption.TopDirectoryOnly))
            .Where(f => !FileHelper.CheckIfFileInUse(filesInUseCollection, f))
            .SelectMany(f => Observable.Start(() => FileHelper.SendFileToApi(userid, f)), (f, s) => new { file = f, success = s })
            .Where(x => x.success)
            .Select(x => x.file);
    
    IDisposable subscription =
        clearMissedFiles
            .Subscribe(f => File.Delete(f));
    

    这将监视文件系统并定期检查。并并行调用API,并且尝试一次删除多个文件不会导致操作系统的痛苦。

    打个电话就行了 subscription.Dispose() 在离开前进行清理。

    位的NuGet“System.Reactive”,然后引用 using System.Reactive.Linq 用于显示扩展。