confuse about EndUploadFromStream - azure-storage

I am confusing with a problem about upload blobs asynchronously, hopes find answer here.
Please take a look at my code snippet first,
public void UploadMultipleBlobs(List<string> filelocations, string containerName, AsyncCallback callback = null, string path = null)
{
try
{
Parallel.ForEach(filelocations, fileLocation =>
{
//File to Stream
MemoryStream str = new MemoryStream();
byte[] file = File.ReadAllBytes(fileLocation);
str.Write(file, 0, file.Length);
str.Seek(0, SeekOrigin.Begin);
//Operations
if (callback == null)
callback = new AsyncCallback(OnUploadCompleted);
BlobRequestOptions blobRequestOptions = new BlobRequestOptions();
blobRequestOptions.Timeout = new TimeSpan(1, 0, 0);
blobRequestOptions.RetryPolicy = retry;
CloudBlob currentBlob = container.GetBlobReference(blobName);
var result = currentBlob.BeginUploadFromStream(str, blobRequestOptions, callback, new Object[] { currentBlob, str });
currentBlob.EndUploadFromStream(result);
});
}
catch
{
throw;
}
}
private void OnUploadCompleted(IAsyncResult result)
{
try
{
// Get array passed to callback
Object[] states = (Object[])result.AsyncState;
var blob = (CloudBlob)states[0];
var stream = (MemoryStream)states[1];
// End the operation
//blob.EndUploadFromStream(result);
// Close the stream
stream.Close();
}
catch
{
throw;
}
}
I need to upload mutil files to Azure blob, number of files may be 10-50,000, each file is about 10KB-50KB. The code snippet works fine for me currently. However, if I call EndUploadFromStream in callback, it always throw an exception when uploading over 2,000 files. I mean if I remove EndUploadFromStream in upload method and call EndUploadFromStream in callback(OnUploadCompleted method), the exception happens. The exception message as below:
Unable to read data from the transport connection: The connection was closed., StackTrace: at Microsoft.WindowsAzure.StorageClient.Tasks.Task`1.get_Result()
at Microsoft.WindowsAzure.StorageClient.CloudBlob.EndUploadFromStream(IAsyncResult asyncResult)
I don't know why it happens...hopes got answer from you guys.
Thanks.

The Begin/End code looks OK. I notice that you're not doing anything to wait for the asynchronous operations to complete, so the problem may be related to that. eg, if you're running this from a console application then the application may exit before all the uploads have completed and then give you those errors. That would not be a problem if the EndUploadFromStream() call is inside the Parallel.ForEach() because it will cause the Parallel.ForEach() call to block until all the uploads have completed.
So try adding code to wait for all the uploads to complete and see if that fixes it. A simple way would be a counter that is initialized to the total number of uploads, and then decremented (using Interlocked.Decremement() for thread safety) inside of the callback. Another options would be use Task.FromAsync() to get an array of Task objects, then using Task.WaitAll() to wait for them to complete.
As an aside, using both Parallel.ForEach() and Begin/End methods at the same time is usually redundant - Begin/End is asynchronous already so there's usually no point using multiple threads to invoke it. Since you have such a big list of items it might make some difference in this case, but probably not much. You're probably better off using a simple foreach loop instead of Parallel.ForEach() unless you've actually measured a significant difference.

Related

Convert writes to OutputStream into a Flux<DataBuffer> usable by ServerResponse

I have a legacy library that I have to use to retrieve a file. This legacy library doesn't return in InputStream, as you usually expect for reading stuff, but it expects that it is passed an open OutputStream, that it can write to.
I have to write a Webflux REST service, that writes this OutputStream to the org.springframework.web.reactive.function.server.ServerResponse body.
legacyLib.BlobRead(outputStream); // writes the stream to an outputstream, that has to be provided by me, and somehow has to end up in the ServerResponse
Since I want to pass along the Stream directly to the ServerResponse, I probably have to do something like this, right?
ServerResponse.ok().body(magicOutpuStreamToFluxConverter(), DataBuffer.class);
Here is the part of the RequestHandler that's important. I left out some errorhandling/catching of exceptions, that might generally not be needed. Note that I publishedOn a different Scheduler for the read (or at least, that's what I wanted to do), so that this blocking read doesn't interfere with my main event thread:
private Mono<ServerResponse> writeToServerResponse(#NotNull FPTag tag) {
final long blobSize = tag.getBlobSize();
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(Flux.<DataBuffer>create((FluxSink<DataBuffer> emitter) -> {
// for a really big blob I want to read it in chunks, so that my server doesn't use too much memory
for(int i = 0; i < blobSize; i+= tagChunkSize) {
// new DataBuffer that is written to, then emitted later
DefaultDataBuffer dataBuffer = new DefaultDataBufferFactory().allocateBuffer();
try (OutputStream outputStream = dataBuffer.asOutputStream()) {
// write to the outputstream of DataBuffer
tag.BlobReadPartial(outputStream, i, tagChunkSize, FPLibraryConstants.FP_OPTION_DEFAULT_OPTIONS);
// don't know if flushing is strictly neccessary
outputStream.flush();
} catch (IOException | FPLibraryException e) {
log.error("Error reading + writing from tag to http outputstream", e);
emitter.error(e);
}
emitter.next(dataBuffer);
}
// if blob is finished, send "complete" to my flux of DataBuffers
emitter.complete();
}, FluxSink.OverflowStrategy.BUFFER).publishOn(Schedulers.newElastic("centera")).doOnComplete(() -> closeQuietly(tag)), DataBuffer.class);
}

WCF Streaming - who closes the file?

According to Microsoft's samples, here's how one would go about streaming a file throuhg WCF:
// Service class which implements the service contract
public class StreamingService : IStreamingSample
{
public System.IO.Stream GetStream(string data)
{
//this file path assumes the image is in
// the Service folder and the service is executing
// in service/bin
string filePath = Path.Combine(
System.Environment.CurrentDirectory,
".\\image.jpg");
//open the file, this could throw an exception
//(e.g. if the file is not found)
//having includeExceptionDetailInFaults="True" in config
// would cause this exception to be returned to the client
try
{
FileStream imageFile = File.OpenRead(filePath);
return imageFile;
}
catch (IOException ex)
{
Console.WriteLine(
String.Format("An exception was thrown while trying to open file {0}", filePath));
Console.WriteLine("Exception is: ");
Console.WriteLine(ex.ToString());
throw ex;
}
}
...
Now, how do I know who's responsible for releasing the FileStream when the transfer is done?
EDIT: If the code is put inside a "using" block the stream gets shut down before the client receives anything.
The service should clean up and not the client. WCF's default for OperationBehaviorAttribute.AutoDisposeParameters seems to be true, therefore it should do the disposing for you. Although there doesn't seem to be a fixed answer on this.
You could try using the OperationContext.OperationCompleted Event:
OperationContext clientContext = OperationContext.Current;
clientContext.OperationCompleted += new EventHandler(delegate(object sender, EventArgs args)
{
if (fileStream != null)
fileStream.Dispose();
});
Put that before your return.
Check this blog
Short answer: the calling code, via a using block.
Long answer: sample code should never be held up as an exemplar of good practice, it's only there to illustrate one very specific concept. Real code would never have a try block like that, it adds no value to the code. Errors should be logged at the topmost level, not down in the depths. Bearing that in mind, the sample becomes a single expression, File.OpenRead(filePath), that would be simply plugged into the using block that requires it.
UPDATE (after seeing more code):
Just return the stream from the function, WCF will decide when to dispose it.
The stream needs to be closed by party who is responsible to read it. For example, if service returns the stream to client, it's client application responsibility close the stream as Service doesn't know or have control when client finishes reading stream. Also, WCF will not take care of closing the stream again because of the fact that it doesn't know when receiving party has finished reading. :)
HTH,
Amit Bhatia

Async WCF Service with multiple async calls inside

I have a web service in WCF that consume some external web services, so what I want to do is make this service asynchronous in order to release the thread, wait for the completion of all the external services, and then return the result to the client.
With Framework 4.0
public class MyService : IMyService
{
public IAsyncResult BeginDoWork(int count, AsyncCallback callback, object serviceState)
{
var proxyOne = new Gateway.BackendOperation.BackendOperationOneSoapClient();
var proxyTwo = new Gateway.BackendOperationTwo.OperationTwoSoapClient();
var taskOne = Task<int>.Factory.FromAsync(proxyOne.BeginGetNumber, proxyOne.EndGetNumber, 10, serviceState);
var taskTwo = Task<int>.Factory.FromAsync(proxyTwo.BeginGetNumber, proxyTwo.EndGetNumber, 10, serviceState);
var tasks = new Queue<Task<int>>();
tasks.Enqueue(taskOne);
tasks.Enqueue(taskTwo);
return Task.Factory.ContinueWhenAll(tasks.ToArray(), innerTasks =>
{
var tcs = new TaskCompletionSource<int>(serviceState);
int sum = 0;
foreach (var innerTask in innerTasks)
{
if (innerTask.IsFaulted)
{
tcs.SetException(innerTask.Exception);
callback(tcs.Task);
return;
}
if (innerTask.IsCompleted)
{
sum = innerTask.Result;
}
}
tcs.SetResult(sum);
callback(tcs.Task);
});
}
public int EndDoWork(IAsyncResult result)
{
try
{
return ((Task<int>)result).Result;
}
catch (AggregateException ex)
{
throw ex.InnerException;
}
}
}
My questions here are:
This code is using three threads: one that is instanced in the
BeginDoWork, another one that is instanced when the code enter
inside the anonymous method ContinueWhenAll, and the last one when
the callback is executed, in this case EndDoWork. Is that correct or
I’m doing something wrong on the calls? Should I use any
synchronization context? Note: The synchronization context is null
on the main thread.
What happen if I “share” information between
threads, for instance, the callback function? Will that cause a
performance issue or the anonymous method is like a closure where I
can share data?
With Framework 4.5 and Async and Await
Now with Framework 4.5, the code seems too much simple than before:
public async Task<int> DoWorkAsync(int count)
{
var proxyOne = new Backend.ServiceOne.ServiceOneClient();
var proxyTwo = new Backend.ServiceTwo.ServiceTwoClient();
var doWorkOne = proxyOne.DoWorkAsync(count);
var doWorkTwo = proxyTwo.DoWorkAsync(count);
var result = await Task.WhenAll(doWorkOne, doWorkTwo);
return doWorkOne.Result + doWorkTwo.Result;
}
But in this case when I debug the application, I always see that the code is executed on the same thread. So my questions here are:
3.. When I’m waiting for the “awaitable” code, is that thread released and goes back to the thread pool to execute more requests?
3.1. If So, I suppose that when I get a result from the await Task, the execution completes on the same thread that the call before. Is that possible? What happen if that thread is processing another request?
3.2 If Not, how can I release the thread to send it back to the thread pool with Asycn and Await pattern?
Thank you!
1. This code is using three threads: one that is instanced in the BeginDoWork, another one that is instanced when the code enter inside the anonymous method ContinueWhenAll, and the last one when the callback is executed, in this case EndDoWork. Is that correct or I’m doing something wrong on the calls? Should I use any synchronization context?
It's better to think in terms of "tasks" rather than "threads". You do have three tasks here, each of which will run on the thread pool, one at a time.
2. What happen if I “share” information between threads, for instance, the callback function? Will that cause a performance issue or the anonymous method is like a closure where I can share data?
You don't have to worry about synchronization because each of these tasks can't run concurrently. BeginDoWork registers the continuation just before returning, so it's already practically done when the continuation can run. EndDoWork will probably not be called until the continuation is complete; but even if it is, it will block until the continuation is complete.
(Technically, the continuation can start running before BeginDoWork completes, but BeginDoWork just returns at that point, so it doesn't matter).
3. When I’m waiting for the “awaitable” code, is that thread released and goes back to the thread pool to execute more requests?
Yes.
3.1. If So, I suppose that when I get a result from the await Task, the execution completes on the same thread that the call before. Is that possible? What happen if that thread is processing another request?
No. Your host (in this case, ASP.NET) may continue the async methods on any thread it happens to have available.
This is perfectly safe because only one thread is executing at a time.
P.S. I recommend
var result = await Task.WhenAll(doWorkOne, doWorkTwo);
return result[0] + result[1];
instead of
var result = await Task.WhenAll(doWorkOne, doWorkTwo);
return doWorkOne.Result + doWorkTwo.Result;
because Task.Result should be avoided in async programming.

Async Web Service call from Silverlight 3

I have a question regarding the sequencing of events in the scenario where you are calling a wcf service from silverlight 3 and updating the ui on a seperate thread. Basically, I would like to know whether what I am doing is correct... Sample is as follows. This is my first post on here, so bear with me, because i am not sure how to post actual code. Sample is as follows :
//<summary>
public static void Load(string userId)
{
//Build the request.
GetUserNameRequest request =
new GetUserNameRequest { UserId = userId };
//Open the connection.
instance.serviceClient = ServiceController.UserService;
//Make the request.
instance.serviceClient.GetUserNameCompleted
+= UserService_GetUserNameCompleted;
instance.serviceClient.GetGetUserNameAsync(request);
return instance.VM;
}
/// <summary>
private static void UserService_GetUserNameCompleted(object sender, GetUserNameCompletedEventArgs e)
{
try
{
Controller.UIDispatcher.BeginInvoke(() =>
{
//Load the response.
if (e.Result != null && e.Result.Success)
{
LoadResponse(e.Result);
}
//Completed loading data.
});
}
finally
{
instance.serviceClient.GetUserNameCompleted
-= UserService_GetUserNameCompleted;
ServiceHelper.CloseService(instance.serviceClient);
}
}
So my question basically is, inside of my UI thread when I am loading the response if that throws an exception, will the "finally" block catch that ? If not, should i put another try/catch inside of the lambda where I am loading the response ?
Also, since I am executing the load on the ui thread, is it possible that the finally will execute before the UI thread is done updating ? And could as a result call the Servicehelper.CloseService() before the load has been done ?
I ask because I am having intermittent problems using this approach.
The finally block should get executed before the processing of the response inside the BeginInvoke. BeginInvoke means that the code will get executed in the next UI cycle.
Typically the best approach to this type of thing is to pull all the data you need out of the response and store it in a variable and then clean up your service code. Then make a call to BeginInvoke and update the UI using the data in the variable.

How to Force an Exception from a Task to be Observed in a Continuation Task?

I have a task to perform an HttpWebRequest using
Task<WebResponse>.Factory.FromAsync(req.BeginGetRespone, req.EndGetResponse)
which can obviously fail with a WebException. To the caller I want to return a Task<HttpResult> where HttpResult is a helper type to encapsulate the response (or not). In this case a 4xx or 5xx response is not an exception.
Therefore I've attached two continuations to the request task. One with TaskContinuationOptions OnlyOnRanToCompletion and the other with OnlyOnOnFaulted. And then wrapped the whole thing in a Task<HttpResult> to pick up the one result whichever continuation completes.
Each of the three child tasks (request plus two continuations) is created with the AttachedToParent option.
But when the caller waits on the returned outer task, an AggregateException is thrown is the request failed.
I want to, in the on faulted continuation, observe the WebException so the client code can just look at the result. Adding a Wait in the on fault continuation throws, but a try-catch around this doesn't help. Nor does looking at the Exception property (as section "Observing Exceptions By Using the Task.Exception Property" hints here).
I could install a UnobservedTaskException event handler to filter, but as the event offers no direct link to the faulted task this will likely interact outside this part of the application and is a case of a sledgehammer to crack a nut.
Given an instance of a faulted Task<T> is there any means of flagging it as "fault handled"?
Simplified code:
public static Task<HttpResult> Start(Uri url) {
var webReq = BuildHttpWebRequest(url);
var result = new HttpResult();
var taskOuter = Task<HttpResult>.Factory.StartNew(() => {
var tRequest = Task<WebResponse>.Factory.FromAsync(
webReq.BeginGetResponse,
webReq.EndGetResponse,
null, TaskCreationOptions.AttachedToParent);
var tError = tRequest.ContinueWith<HttpResult>(
t => HandleWebRequestError(t, result),
TaskContinuationOptions.AttachedToParent
|TaskContinuationOptions.OnlyOnFaulted);
var tSuccess = tRequest.ContinueWith<HttpResult>(
t => HandleWebRequestSuccess(t, result),
TaskContinuationOptions.AttachedToParent
|TaskContinuationOptions.OnlyOnRanToCompletion);
return result;
});
return taskOuter;
}
with:
private static HttpDownloaderResult HandleWebRequestError(
Task<WebResponse> respTask,
HttpResult result) {
Debug.Assert(respTask.Status == TaskStatus.Faulted);
Debug.Assert(respTask.Exception.InnerException is WebException);
// Try and observe the fault: Doesn't help.
try {
respTask.Wait();
} catch (AggregateException e) {
Log("HandleWebRequestError: waiting on antecedent task threw inner: "
+ e.InnerException.Message);
}
// ... populate result with details of the failure for the client ...
return result;
}
(HandleWebRequestSuccess will eventually spin off further tasks to get the content of the response...)
The client should be able to wait on the task and then look at its result, without it throwing due to a fault that is expected and already handled.
In the end I took the simplest route I could think of: hide the exception. This is possible because WebException has a property Response which gives access to the HttpWebResponse I want:
var requestTask = Task<WebResponse>.Factory.FromAsync(
webReq.BeginGetResponse,
ia => {
try {
return webReq.EndGetResponse(ia);
} catch (WebException exn) {
requestState.Log(...);
return exn.Response;
}
});
And then handle errors, redirects and success responses in the continuation task.