title: Run async task continuation on native function callback thread
body: <p>I have a C function <code>FsReadStream</code> that does some asynchronous work and takes a callback. When done, it calls the callback using the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms684957(v=vs.85).aspx" rel="nofollow">QueueUserWorkItem</a> windows function.</p>
  
  <p>I am trying to call this function from managed code (c#) using the async/await pattern. So I do the following</p>
  
  <ol>
  <li>Construct a <code>Task</code> object passing the constructor a lambda that returns the result.</li>
  <li>Construct a callback that runs this task using the <code>RunSynchronously</code> method</li>
  <li>Call the asynchronous native function, passing in the callback</li>
  <li>Return the task object to the caller</li>
  </ol>
  
  <p>My code looks something like this</p>
  
  <pre><code>/// Reads into the buffer as many bytes as the buffer size
  public Task&lt;ReadResult&gt; ReadAsync(byte[] buffer)
  {
      GCHandle pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
      IntPtr bytesToRead = Marshal.AllocHGlobal(sizeof(long));
      Marshal.WriteInt64(bytesToRead, buffer.Length);
  
      FsAsyncInfo asyncInfo = new FsAsyncInfo();
      ReadResult readResult = new ReadResult();
  
      Task&lt;ReadResult&gt; readCompletionTask = new Task&lt;ReadResult&gt;(() =&gt; { return readResult; });
      TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
  
      asyncInfo.Callback = (int status) =&gt;
      {
          readResult.ErrorCode = status;
          readResult.BytesRead = (int)Marshal.ReadInt64(bytesToRead);
          readCompletionTask.RunSynchronously(scheduler);
          pinnedBuffer.Free();
          Marshal.FreeHGlobal(bytesToRead);
      };
  
      // Call asynchronous native method    
      NativeMethods.FsReadStream(
                      pinnedBuffer.AddrOfPinnedObject(),
                      bytesToRead,
                      ref asyncInfo);
  
      return readCompletionTask;
  }
  </code></pre>
  
  <p>and I call it like this</p>
  
  <pre><code>ReadResult readResult = await ReadAsync(data);
  </code></pre>
  
  <p>I have two questions</p>
  
  <ol>
  <li>How to make the code that runs after the call to <code>await ReadAsync</code> run on the same thread as the callback? Currently, I see it runs on a different thread even though I am calling <code>readCompletionTask.RunSynchronously</code>. I am running this code under ASP.NET and IIS.</li>
  <li>Does the native <code>QueueUserWorkItem</code> function use the same threadpool as the managed <a href="https://msdn.microsoft.com/en-us/library/kbf0f1ct(v=vs.110).aspx" rel="nofollow">ThreadPool.QueueUserWorkItem</a> method? My opinion was that it should, and therefore it should be possible for the managed <code>TaskScheduler</code> to schedule tasks on the native callback thread.</li>
  </ol>