WCF请求中的多线程写入文本文件

本文关键字:文本 文件 多线程 请求 WCF | 更新日期: 2023-09-27 18:28:42

  1. 我有WCF方法,它应该创建带有一些数据的文件
  2. 此文件有时会被其他系统删除
  3. 如果现有文件存在,我应该附加它
  4. 其他WCF请求不应丢失数据

我考虑了不同的选项,但看起来我应该在WCF中实现队列。

我的想法和尝试:

  1. 已使用TextWriter.Synchronized。我发现Synchronizeds仅适用于为其创建的实例
  2. 每个请求都将创建自己的文件。创建具有最大索引的文件的请求应该将所有文件附加到一个文件中。(当某个请求发生时,该文件已经是最后一个新请求时,将不起作用)
  3. WCF中的一些队列(如何实现?)

测试应用程序(WCF方法WritePartToFile的模拟):

class Program
{
    private static string FileFormat = "file{0}.1001";
    static void Main(string[] args)
    {
        int countOfLines = 100;
        var processesCount = 200;
        var files = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.1001");
        foreach (var file in files)
        {
            File.Delete(file);
        }
        var expectedFilesCount = processesCount * countOfLines;
        Console.WriteLine("Trying to write. Processes:" + processesCount.ToString() + ". Lines:" + countOfLines + ". Expected lines:" + processesCount * countOfLines);
        var tasks = new List<Task>();
        for (int i = 1; i < processesCount; i++)
        {
            var result = Task.Factory.StartNew(() =>
            {
                WritePartToFile("Task:" + i.ToString(), countOfLines);
            });
            tasks.Add(result);
        }
        Console.WriteLine("Wait...");
        Task.WaitAll(tasks.ToArray());
        var fileName = string.Format(FileFormat, "");
        var lines = 0;
        if (File.Exists(fileName))
        {
            lines = File.ReadLines(fileName).Count();
        }
        if (lines != expectedFilesCount)
        {
            Console.WriteLine("Error!!! Total lines  (" + lines + ") != expected (" + expectedFilesCount + ")");
        }
        Console.WriteLine("Done. Lines added:" + lines + " Any key to exit.");
        Console.Read();
    }
    public static void WritePartToFile(string taskName, int countOfLines)
    {
        // Find free file name.
        var fileName = string.Format(FileFormat, "temp_1");
        int fileIndex = 1;
        while (File.Exists(fileName))
        {
            fileIndex++;
            fileName = string.Format(FileFormat, "temp_" + fileIndex);
        }
        var logFileStream = new FileStream(fileName, FileMode.Append, FileAccess.Write, FileShare.Read);
        using (var myWriter = new StreamWriter(logFileStream))
        {
            for (int i = 1; i < countOfLines; i++)
            {
                myWriter.WriteLine(taskName + ". Line number: " + i.ToString() + ". Guid:" + Guid.NewGuid().ToString());
            }
        }
        // Check is current file has MAX index (next index doesnot exists). Merge items (doesnot working)
        var nextFile = string.Format(FileFormat, "temp_" + fileIndex + 1);
        if (!File.Exists(nextFile))
        {
            var destinationFileName = string.Format(FileFormat, "");
            var mergedLines = new List<string>();
            // Merge all files into destination.
            var files = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.1001");
            foreach (var file in files)
            {
                if (File.Exists(file))
                {
                    mergedLines.AddRange(File.ReadAllLines(file));
                }
            }
            logFileStream = new FileStream(destinationFileName, FileMode.Append, FileAccess.Write, FileShare.None);
            using (var myWriter = new StreamWriter(logFileStream))
            {
                foreach (var item in mergedLines)
                {
                    myWriter.WriteLine(item);
                }
            }
        }
    }
}

附言:我无法将此WCF方法设置为同步,因为有些请求会将数据写入其他文件,因此不需要同步。

WCF请求中的多线程写入文本文件

您正在创建多个FileStreams,每个任务一个,这似乎不正确。即使他们是同步的,他们之间也不会同步,因为他们无法了解其他人。

您需要做的是在main中创建文件处理程序,然后将其传递给任务。然后,每个任务都将尝试写入同一个FileStream。由于您要求系统的其他部分可以访问此文件,因此您不能一直打开它。

创建一个包含文件处理的新类。这个类将使用适当的锁定来处理同步。然后创建它的一个实例并将其传递给您的Task,这样所有Task都将对该文件具有单一的共享访问权限。在该类中,您可以添加逻辑来检查它是否存在,打开文件并立即关闭