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

带任务的C#异步编程[已关闭]

  •  0
  • Nico  · 技术社区  · 9 年前

    我开始学习异步编程,偶然发现了这个问题。我通过Dispatcher.BeginInvoke调用这些函数。

    我希望得到文件内容表单 ReadText 方法,但我得到的只是“System.Threading.Tasks.Task`1[System.String]”

    所以问题是我的代码有什么问题,我应该修复哪一行?

    可悲的是,我无法弄清楚我的问题在哪里,因为我现在已经有一段时间在关注这种代码的和平。

    我想,因为我取回了对象的时间,而不是对象本身,所以我的ReadText方法是错误的,但我不知道在哪里。我在Stringbuilder下面的部分或我使这些方法异步的方式似乎有问题。

    如果您想知道我为什么使用这两种方法是为了了解await和调用asyncTask方法。我也试着把这种方法变成一种品尝方法,但这只会导致更多的问题。

    提前感谢您的帮助。

        public async void ReadFile()
        {
            string filePath = @"SampleFile.txt";
    
            if (File.Exists(filePath) == false)
            {
                MessageBox.Show(filePath + " not found", "File Error", MessageBoxButton.OK);
            }
            else
            {
                try
                {
                    string text = await ReadText(filePath);                 
                    txtContents.Text = text;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
        }
    
        private async Task<string> ReadText(string filePath)
        {
            Task Readfile = Task.Run(() =>
            {
                using (FileStream sourceStream = new FileStream(filePath,
                    FileMode.Open, FileAccess.Read, FileShare.Read,
                    bufferSize: 4096, useAsync: true))
            {
                StringBuilder sb = new StringBuilder();
    
                byte[] buffer = new byte[0x1000];
                int numRead;
                while ((numRead = sourceStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    string text = Encoding.Unicode.GetString(buffer, 0, numRead);
                    sb.Append(text);
                }
    
                return sb.ToString();
            }
        }
            );
    
            await Readfile;
    
            return Readfile.ToString();
    
        }
    
    2 回复  |  直到 9 年前
        1
  •  3
  •   Dennis_E    9 年前

    您正在返回 string ,所以制作 Readfile Task<string> :

    Task<string> Readfile = Task.Run<string>( ... )
    

    然后你想回来 Readfile.Result; Readfile.ToString();
    但你可以写得更简单:

    return await Readfile;
    

    甚至:

    return await Task.Run<string>( ... )
    
        2
  •  1
  •   Radin Gospodinov    9 年前

    您不需要使用Task。运行以从流中读取,您可以等待方便的方法ReadAsync:

     public async Task ReadFile() {
          string filePath = @"SampleFile.txt";
    
          if (File.Exists(filePath) == false) {
            MessageBox.Show(filePath + " not found", "File Error", MessageBoxButton.OK);
          } else {
            try {
              string text = await ReadText(filePath);
              txtContents.Text = text;
            } catch (Exception ex) {
              Debug.WriteLine(ex.Message);
            }
          }
        }
    
        private async Task<string> ReadText(string filePath) {
    
          using (FileStream sourceStream = new FileStream(filePath,
              FileMode.Open, FileAccess.Read, FileShare.Read,
              bufferSize: 4096, useAsync: true)) {
            StringBuilder sb = new StringBuilder();
    
            byte[] buffer = new byte[0x1000];
            int numRead;
            while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0) {
              string text = Encoding.Unicode.GetString(buffer, 0, numRead);
              sb.Append(text);
            }
    
            return sb.ToString();
          }
    
        }
    

    另外,不建议使用异步void,请尽量避免这种情况。异步void方法具有不同的错误处理语义。当从异步Task或异步Task方法中抛出异常时,将捕获该异常并将其放置在Task对象上。对于异步void方法,没有Task对象,因此从异步void法抛出的任何异常都将直接在异步void启动时处于活动状态的SynchronizationContext上引发。 Best practice for async methods