title: How can I use a method async Task<string> and return string, and then how do I pass a delegate for that method to a constructor and use it later?
body: <p>I have this method that returns <code>string</code>:</p>
  
  <pre><code>public string SendResponse(HttpListenerRequest request)
  {
      string result = "";
      string key = request.QueryString.GetKey(0);
      if (key == "cmd")
      {
          if (request.QueryString[0] == "uploadstatus")
          {
              switch (Youtube_Uploader.uploadstatus)
              {
                  case "uploading file":
                      return "uploading " + Youtube_Uploader.fileuploadpercentages;
  
                  case "status":
                      return Youtube_Uploader.fileuploadpercentages.ToString();
  
                  case "file uploaded successfully":
                      Youtube_Uploader.uploadstatus = "";
                      return "upload completed," + Youtube_Uploader.fileuploadpercentages + ","
                         + Youtube_Uploader.time;
                  default:
                      return "upload unknown state";
              }
  
  
          }
          if (request.QueryString[0] == "nothing")
          {
              return "Connection Success";
          }
          if (request.QueryString[0] == "start")
          {
              StartRecrod();
              result = "Recording started";
          }
  
          if (request.QueryString[0] == "stop")
          {
              dirchanged = false;
              StartRecrod();
              result = "Recording stopped and preparing the file to be shared on youtube";
              string fileforupload = await WatchDirectory();
              await WaitForUnlockedFile(fileforupload);
              using (StreamWriter w = new StreamWriter(userVideosDirectory + "\\UploadedVideoFiles.txt", true))
              {
                  w.WriteLine(fileforupload);
              }
              uploadedFilesList.Add(fileforupload);
              Youtube_Uploader youtubeupload = new Youtube_Uploader(uploadedFilesList[0]);
          }
      }
      else
      {
          result = "Nothing have been done";
      }
  
      return result;
  
  }
  </code></pre>
  
  <p>The problem is that in this method I'm using in two lines <code>await</code>:</p>
  
  <pre><code>string fileforupload = await WatchDirectory();
  await WaitForUnlockedFile(fileforupload);
  </code></pre>
  
  <p>And getting errors on these two lines. Both two errors are the same:</p>
  
  <blockquote>
    <p>Error The 'await' operator can only be used within an async method.
    Consider marking this method with the 'async' modifier and changing
    its return type to <code>'Task&lt;string&gt;'</code>.</p>
  </blockquote>
  
  <p>The question if it's possible to make the <code>SendResponse()</code> method to return string since I need it and also to use the <code>await</code>?</p>
  
  <p>This is the two methods that's why I need to use <code>await</code> in the <code>SendResponse()</code> method:</p>
  
  <pre><code>private async Task&lt;string&gt; WatchDirectory()
  {
      using (FileSystemWatcher watcher = new FileSystemWatcher())
      {
          TaskCompletionSource&lt;string&gt; tcs = new TaskCompletionSource&lt;string&gt;();
  
          watcher.Path = userVideosDirectory;
          watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size;
          watcher.Filter = "*.mp4";
          watcher.Changed += (sender, e) =&gt; tcs.SetResult(e.FullPath);
          watcher.EnableRaisingEvents = true;
  
          return await tcs.Task;
      }
  }
  
  // You can get rid of the OnChanged() method altogether
  
  private async Task WaitForUnlockedFile(string fileName)
  {
      while (true)
      {
          try
          {
              using (IDisposable stream = File.Open(fileName, FileMode.OpenOrCreate,
                  FileAccess.ReadWrite, FileShare.None))
              { /* on success, immediately dispose object */ }
  
              break;
          }
          catch (IOException)
          {
              // ignore exception
              // NOTE: for best results, consider checking the hresult value of
              // the exception, to ensure that you are only ignoring the access violation
              // exception you're expecting, rather than other exceptions, like
              // FileNotFoundException, etc. which could result in a hung process
          }
  
          // You might want to consider a longer delay...maybe on the order of
          // a second or two at least.
          await Task.Delay(100);
      }
  }
  </code></pre>
  
  <p><strong>UPDATE:</strong></p>
  
  <p>I changed the method <code>SendResponse()</code> to be <code>async Task&lt;string&gt;</code>
  But then in the <code>WebServer</code> class constructor I have this and getting error on this line:</p>
  
  <pre><code>WebServer ws = new WebServer(SendResponseAsync, "http://+:8098/");
  </code></pre>
  
  <p>(SendResponseAsync is the SendResponse changed its name)</p>
  
  <p>The error is:</p>
  
  <blockquote>
    <p>Error 1   'System.Threading.Tasks.Task Automatic_Record.Form1.SendResponseAync(System.Net.HttpListenerRequest)' has the wrong return type</p>
  </blockquote>
  
  <p>And WebServer class is:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Net;
  using System.Threading;
  
  namespace Automatic_Record
  {
      class WebServer
      {
          private readonly HttpListener _listener = new HttpListener();
          private readonly Func&lt;HttpListenerRequest, string&gt; _responderMethod;
  
          public WebServer(string[] prefixes, Func&lt;HttpListenerRequest, string&gt; method)
          {
              if (!HttpListener.IsSupported)
                  throw new NotSupportedException(
                      "Needs Windows XP SP2, Server 2003 or later.");
  
              // URI prefixes are required, for example 
              // "http://localhost:8080/index/".
              if (prefixes == null || prefixes.Length == 0)
                  throw new ArgumentException("prefixes");
  
              // A responder method is required
              if (method == null)
                  throw new ArgumentException("method");
  
              foreach (string s in prefixes)
                  _listener.Prefixes.Add(s);
  
              _responderMethod = method;
              _listener.Start();
          }
  
          public WebServer(Func&lt;HttpListenerRequest, string&gt; method, params string[] prefixes)
              : this(prefixes, method) { }
  
          public void Run()
          {
              ThreadPool.QueueUserWorkItem((o) =&gt;
              {
                  Console.WriteLine("Webserver running...");
                  try
                  {
                      while (_listener.IsListening)
                      {
                          ThreadPool.QueueUserWorkItem((c) =&gt;
                          {
                              var ctx = c as HttpListenerContext;
                              try
                              {
                                  string rstr = _responderMethod(ctx.Request);
                                  System.Diagnostics.Trace.Write(ctx.Request.QueryString);
                                  //ctx.Request.QueryString
  
                                  byte[] buf = Encoding.UTF8.GetBytes(rstr);
                                  ctx.Response.ContentLength64 = buf.Length;
                                  ctx.Response.OutputStream.Write(buf, 0, buf.Length);
                                  System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
  
                              }
                              catch { } // suppress any exceptions
                              finally
                              {
                                  // always close the stream
                                  ctx.Response.OutputStream.Close();
                              }
                          }, _listener.GetContext());
                      }
                  }
                  catch { } // suppress any exceptions
              });
          }
  
          public void Stop()
          {
              _listener.Stop();
              _listener.Close();
          }
      }
  }
  </code></pre>
  
  <p>UPDATE 2</p>
  
  <p>I tried peter solution so i changed the WebServer class code to the one Peter show in this question solution.</p>
  
  <p>Then in form1 constructor i did:</p>
  
  <pre><code>var ws = new WebServer(
              () =&gt; Task.Run(request =&gt; SendResponseAsync(request)),
              "http://+:8098/");
              ws.Run();
  </code></pre>
  
  <p>Then the method SendResponseAsync:</p>
  
  <pre><code>public async Task&lt;string&gt; SendResponseAsync(HttpListenerRequest request)
          {
              string result = "";
              string key = request.QueryString.GetKey(0);
              if (key == "cmd")
              {
                  if (request.QueryString[0] == "uploadstatus")
                  {
                      switch (Youtube_Uploader.uploadstatus)
                      {
                          case "uploading file":
                              return "uploading " + Youtube_Uploader.fileuploadpercentages;
  
                          case "status":
                              return Youtube_Uploader.fileuploadpercentages.ToString();
  
                          case "file uploaded successfully":
                              Youtube_Uploader.uploadstatus = "";
  
                              return "upload completed," + Youtube_Uploader.fileuploadpercentages + ","
                                 + Youtube_Uploader.time;
  
                          default:
                              return "upload unknown state";
                      }
  
  
                  }
                  if (request.QueryString[0] == "nothing")
                  {
  
                      return "Connection Success";
                  }
                  if (request.QueryString[0] == "start")
                  {
                      StartRecrod();
                      result = "Recording started";
                  }
  
  
                  if (request.QueryString[0] == "stop")
                  {
                      dirchanged = false;
                      StartRecrod();
                      result = "Recording stopped and preparing the file to be shared on youtube";
                      string fileforupload = await WatchDirectory();
                      await WaitForUnlockedFile(fileforupload);
                      using (StreamWriter w = new StreamWriter(userVideosDirectory + "\\UploadedVideoFiles.txt", true))
                      {
                          w.WriteLine(fileforupload);
                      }
                      uploadedFilesList.Add(fileforupload);
                      Youtube_Uploader youtubeupload = new Youtube_Uploader(uploadedFilesList[0]);
                  }
  
  
              }
              else
              {
                  result = "Nothing have been done";
              }
  
              return result;
  
          }
  </code></pre>
  
  <p>The WatchDirectory:</p>
  
  <pre><code>private async Task&lt;string&gt; WatchDirectory()
          {
              using (FileSystemWatcher watcher = new FileSystemWatcher())
              {
                  TaskCompletionSource&lt;string&gt; tcs = new TaskCompletionSource&lt;string&gt;();
  
                  watcher.Path = userVideosDirectory;
                  watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size;
                  watcher.Filter = "*.mp4";
                  watcher.Changed += (sender, e) =&gt; tcs.SetResult(e.FullPath);
                  watcher.EnableRaisingEvents = true;
  
                  return await tcs.Task;
              }
          }
  </code></pre>
  
  <p>And last the WaitForUnlockedFile</p>
  
  <pre><code>private async Task WaitForUnlockedFile(string fileName)
          {
              while (true)
              {
                  try
                  {
                      using (IDisposable stream = File.Open(fileName, FileMode.OpenOrCreate,
                          FileAccess.ReadWrite, FileShare.None))
                      { /* on success, immediately dispose object */ }
  
                      break;
                  }
                  catch (IOException)
                  {
                      // ignore exception
                      // NOTE: for best results, consider checking the hresult value of
                      // the exception, to ensure that you are only ignoring the access violation
                      // exception you're expecting, rather than other exceptions, like
                      // FileNotFoundException, etc. which could result in a hung process
                  }
  
                  // You might want to consider a longer delay...maybe on the order of
                  // a second or two at least.
                  await Task.Delay(100);
              }
      }
  </code></pre>
  
  <p>But getting error on the line:</p>
  
  <p>Task.Run
  Severity Code   Description Project File    Line Error Cannot convert lambda expression to type 'string[]' because it is not a delegate type    Automatic_Record    </p>
  
  <p>And also error on the line "<a href="http://+:8098/" rel="nofollow">http://+:8098/</a>" 
  Severity    Code    Description Project File    Line Error Argument 2: cannot convert from 'string' to 'System.Func></p>