Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dispose a MemoryStream that is used in a Task?

I have the following method:

public void Write() {
     var tasks = new List<Task>();
     while(...) {
         var memoryStream = new MemoryStream(...);
         var task = _pageBlob.WritePagesAsync(memoryStream, ... );
         tasks.Add(task);
     }    
     Task.WaitAll(tasks.ToArray());
}

How to correctly dispose memoryStream that in Task? I need to dispose the memoryStream object when the task is finished.

like image 496
Anatoly Avatar asked Apr 28 '16 14:04

Anatoly


People also ask

How do I dispose of MemoryStream?

MemoryStream does not have any unmanaged resources to dispose, so you don't technically have to dispose of it. The effect of not disposing a MemoryStream is roughly the same thing as dropping a reference to a byte[] -- the GC will clean both up the same way.

What is the difference between Stream and MemoryStream?

You would use the FileStream to read/write a file but a MemoryStream to read/write in-memory data, such as a byte array decoded from a string. You would not use a Stream in and of itself, but rather use it for polymorphism, i.e. passing it to methods that can accept any implementation of Stream as an argument.


2 Answers

You have two options:

1-Encapsulate all the process inside a task:

while(...) {

     var task = Task.Run(async () => {

         var memoryStream = new MemoryStream(...);
         var res = await _pageBlob.WritePagesAsync(memoryStream, ... );
         memoryStream.Dispose();

     });

     tasks.Add(task);
 }    

2-Use a Continuation:

 while(...) {
     var memoryStream = new MemoryStream(...);
     var task = _pageBlob.WritePagesAsync(memoryStream, ... )
                .ContinueWith((PrevTask) => memoryStream.Dispose());

     tasks.Add(task);
 }    
like image 198
Gusman Avatar answered Sep 18 '22 11:09

Gusman


Split out your while loop body into a separate async method:

private async Task WriteAsync(...)
{
  using (var memoryStream = new MemoryStream(...))
  {
    await _pageBlob.WritePagesAsync(memoryStream, ...);
  }
}

Then use your new method:

public void Write() {
  var tasks = new List<Task>();
  while(...) {
    tasks.Add(WriteAsync(...));
  }    
  Task.WaitAll(tasks.ToArray());
}

On a side note, blocking on asynchronous code (Task.WaitAll) is not generally a good idea. A more natural approach is to keep it asynchronous:

public async Task WriteAsync() {
  var tasks = new List<Task>();
  while(...) {
    tasks.Add(WriteAsync(...));
  }    
  await Task.WhenAll(tasks);
}
like image 28
Stephen Cleary Avatar answered Sep 19 '22 11:09

Stephen Cleary