简体   繁体   English

使用代理进行异步调用

[英]Asynchronous Call using Delegate

I want that separate Async threads of method splitFile should run so that the task will become faster but below code is not working. 我希望单独运行方法splitFile异步线程,以使任务变得更快,但以下代码无法正常工作。 When I debug , it reaches till line RecCnt = File.ReadAllLines(SourceFile).Length - 1; 当我调试时,直到行RecCnt = File.ReadAllLines(SourceFile).Length - 1;为止RecCnt = File.ReadAllLines(SourceFile).Length - 1; and comes out. 然后出来 Please help. 请帮忙。

public delegate void SplitFile_Delegate(FileInfo file);

static void Main(string[] args)
{ 
     DirectoryInfo d = new DirectoryInfo(@"D:\test\Perf testing Splitter"); //Assuming Test is your Folder
     FileInfo[] Files = d.GetFiles("*.txt"); //Getting Text files

     foreach (FileInfo file in Files)
     {
         SplitFile_Delegate LocalDelegate = new SplitFile_Delegate(SplitFile);

         IAsyncResult R = LocalDelegate.BeginInvoke(file, null, null); //invoking the method
         LocalDelegate.EndInvoke(R);

      }
}

private static void SplitFile(FileInfo file)
{
     try
     {
         String fname;
         //int FileLength;
         int RecCnt;
         int fileCount;
         fname = file.Name;
         String SourceFile = @"D:\test\Perf testing Splitter\" + file.Name;


         RecCnt = File.ReadAllLines(SourceFile).Length - 1;
         fileCount = RecCnt / 10000;

         FileStream fs = new FileStream(SourceFile, FileMode.Open);
         using (StreamReader sr = new StreamReader(fs))
         {
             while (!sr.EndOfStream)
             {
                 String dataLine = sr.ReadLine();
                 for (int x = 0; x < (fileCount + 1); x++)
                 {
                      String Filename = @"D:\test\Perf testing Splitter\Destination Files\" + fname + "_" + x + "by" + (fileCount + 1) + ".txt"; //test0by4
                      using (StreamWriter Writer = file.AppendText(Filename))
                      {
                          for (int y = 0; y < 10000; y++)
                          {
                              Writer.WriteLine(dataLine);
                              dataLine = sr.ReadLine();
                          }
                          Writer.Close();
                      }

                  }
              }
          }
     }
     catch (Exception ex)
     {
          Console.WriteLine(ex.Message);
     }
}

Your code doesn't really need any multi-threading. 您的代码实际上不需要任何多线程。 It doesn't really even need asynchronous processing all that much - you're saturating the I/O most likely, and unless you've got multiple drives as the data sources, you're not going to improve that by adding parallelism. 它实际上甚至不需要太多的异步处理-您很可能会使I / O饱和,除非您有多个驱动器作为数据源,否则您将不会通过添加并行性来改善这种情况。

On the other hand, your code is reading each file twice . 另一方面,您的代码将每个文件读取两次 For no reason, wasting memory, time and even CPU. 毫无理由地浪费了内存,时间甚至CPU。 Instead, just do this: 相反,只需执行以下操作:

FileStream fs = new FileStream(SourceFile, FileMode.Open);
using (StreamReader sr = new StreamReader(fs))
{
    string line;
    string fileName = null; 
    StreamWriter outputFile = null;
    int lineCounter = 0;
    int outputFileIndex = 0;

    while ((line = sr.ReadLine()) != null)
    {
        if (fileName == null || lineCounter >= 10000)
        {
            lineCounter = 0;
            outputFileIndex++;
            fileName = @"D:\Output\" + fname + "_" + outputFileIndex + ".txt";

            if (outputFile != null) outputFile.Dispose();
            outputFile = File.AppendText(fileName);
        }

        outputFile.WriteLine(line);
        lineCounter++;
    }
}

If you really need to have the filename in format XOutOfY , you can just rename them afterwards - it's a lot cheaper than reading the source file twice, line after line. 如果确实需要使用XOutOfY格式的文件名,则可以随后对其进行重命名-这比逐行读取源文件两次便宜得多。 Or, if you don't care about keeping the whole file in memory at once, just use the array you got from ReadAllLines and iterate over that, rather than doing the reading all over again. 或者,如果您不希望一次将整个文件保存在内存中,则只需使用从ReadAllLines获得的数组并对其进行迭代,而不是重新进行一次读取。

To make this even easier, you can also use foreach (var line in File.ReadLines(fileName)) . 为了使此操作更加容易,您还可以使用foreach (var line in File.ReadLines(fileName))

If you really want to make this asynchronous, the way to handle that is by using asynchronous I/O, not just by spooling new threads. 如果您真的想使它异步,则处理方法是使用异步I / O,而不仅仅是假脱机新线程。 So you can use await with StreamReader.ReadLineAsync etc. 因此,您可以将StreamReader.ReadLineAsync等与await一起使用。

You are not required to call EndInvoke and really all EndInvoke does is wait on the return value for you. 您不需要调用EndInvoke,实际上EndInvoke所做的只是等待返回值。 Since SplitFile returns void, my guess is there's an optimization that kicks in because you don't need to wait on anything and it simply ignores the wait. 由于SplitFile返回void,所以我猜想会有一个优化启动,因为您不需要等待任何事情,而只是忽略了等待。 For more details: C# Asynchronous call without EndInvoke? 有关更多详细信息: 没有EndInvoke的C#异步调用?

That being said, your usage of Begin/EndInvoke will likely not be faster than serial programming (and will likely be marginally slower) as your for loop is still serialized, and you're still running the iteration in serial. 话虽这么说,因为您的for循环仍处于序列化状态,并且您仍在以串行方式运行迭代,因此Begin / EndInvoke的使用可能不会比串行编程快(并且可能会稍微慢一些)。 All that has changed is you're using a delegate where it looks like one isn't necessary. 发生的所有更改是您正在使用似乎不需要的委托。

It's possible that what you meant to use was Parallel.ForEach (MSDN: https://msdn.microsoft.com/en-us/library/dd992001(v=vs.110).aspx ) which will potentially run iterations in parallel. 您可能要使用的是Parallel.ForEach(MSDN: https ://msdn.microsoft.com/en-us/library/dd992001( v=vs.110 ) .aspx ),它将潜在地并行运行迭代。

Edit: As someone else has mentioned, having multiple threads engage in file operations will likely not improve performance as your file ops are probably disk bound. 编辑:正如其他人所提到的,由于文件操作可能受磁盘限制,因此有多个线程参与文件操作可能不会提高性能。 The main benefit you would get from an async file read/write would probably be unblocking the main thread for a UI update. 您将从异步文件读取/写入中获得的主要好处可能是解锁UI更新的主线程。 You will need to specify what you want with "performance" if you want a better answer. 如果您想获得更好的答案,则需要使用“性能”指定所需的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM