I'm working on a file upload and want to show a progress bar in the UI.
The Controller works something like this:
1. public async Task Upload([FromForm] RequestModel request)
2. fileService.save(request.file); // THIS CAN TAKE LONGER
3. return Ok();
I'm using Angular as following:
this.http.post<ResponseModel>('ENDPOINT', formData, {
reportProgress: true,
observe: 'events',
});
That basically works, however the upload progress that is reported gets to 100% when the file is uploaded to the server successfully (into memory/tmp location) and when the execution is landing in line 1. it already reports 100%;
What I want is to be able to manipulate that Event so that 100% is just reported after line 2. (or 3.) are finished.
I thought about creating another endpoint which can return an int (progress percentage) that is being set in the upload method however it would be much nicer if there is a way without it since it would mean less code and additionally I wouldn't have to juggle between the two numbers (upload to memory + new progress percentage variable).
Is there a way to change the progress event in .Net?
Something like this
> REPORT PROGRESS but only until 60 % (because we still need to do something)
public async Task Upload([FromForm] RequestModel request)
> REPORT PROGRESS = "60 %"; // if necessary, 60 because we still need to save
fileService.save(request.file); // THIS CAN TAKE LONGER
> REPORT PROGRESS = "100%";
return Ok();
It reports upload progress (using XMLHttpRequest events), obviously upload is completed when controller action is reached.
You have to emulate 'correct' progress on UI, for example use multiplier 0.9 for progress events, so it will report 90% when upload is finished then add 10% when this.http.post call is finished.
Related
I have to create a Windows application where i will upload multiple file to azure file share storage and i need to show the multiple file upload progress using progress bar control in windows for application.
I want to show the dynamic progress bar on windows form with each upload iteration of file upload.
Can any one suggest with sample loop iteration for upload with multiple file using progress bar on windows form.
Assuming you are referring to Blob Storage.
UploadFromFileAsync(String, AccessCondition, BlobRequestOptions, OperationContext, IProgress, CancellationToken)
A IProgress object to handle StorageProgress messages.
StorageProgress Class
Holds information about the progress data transfers for both request
and response streams in a single operation.
A nice little example on their site, allbeit a stream example
CancellationToken cancellationToken = new CancellationToken();
IProgress<StorageProgress> progressHandler = new Progress<StorageProgress>(
progress => Console.WriteLine("Progress: {0} bytes transferred", progress.BytesTransferred)
);
await blob.UploadFromStreamAsync(
srcStream,
default(AccessCondition),
default(BlobRequestOptions),
default(OperationContext),
progressHandler,
cancellationToken
);
So where to from here. Because this is IO bound work its best not use Parallel.For or Parallel.ForEach its a waste of resources.
However, ActionBlock Class in the TPL dataflow can be suited, or just async/await pattern with Task.WaitAll Method.
Dataflow example
var block = new ActionBlock<MySomething>(
mySomething => MyMethodAsync(mySomething),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 50 });
foreach (var something in ListOfSomethings)
{
block.Post(something );
}
block.Complete();
await block.Completion;
So without writing the rest of the code for you
Simply add up the size in bytes of your files before you start youy transfers.
Create your progress handlers, and associate them with your tasks
Possibly keep the transferred amount with your tasks
On progress (in thread safe manner) or just on a timmer (in a thread safe manner) sum your progress against the expected amount
Obviously there are details left out of here, however you are now a programmer and its your mission (if you choose to accept it) to figure it out.. free lunch given, and i look forward to your next questions about everything in between :)
I have a scenario in which I have to fetch xml file of customer from api call and then save it in my computer on first request and after that every request of that customer will use my computer file to get data of particular customer.
for example if I have two customers ABC and XYZ. let say first request come for ABC I want to start downloading file of ABC. while downloading is in progress let say first request of XYZ comes. I want to proceed downloading of XYZ customer file as well. but lets say while downloading is in progress for ABC and another request of ABC comes I should let it wait till file of ABC is downloading and after the file will be download I want to get data of 2nd request from that file.
I think about 2 solutions for eg if I lock code of downloading
// code
lock(obj)
{
DownloadXmle("ABC");
}
// code
2nd option is if I declare a static list and before downloading file i push customer number in that list and for all other requests of that customer it checks if institution number is in that list it should wait
//code
currentlyDownloadingFileList.add("ABC");
DownloadXmle("ABC");
currentlyDownloadingFileList.Remove("ABC");
//code
is there any better thing for that?
You should use a ConcurrentDictionary<string, object> to store a thread-safe map of customers to lock objects.
Use GetOrAdd() to safely get a lock object for the customer, then lock on that object.
To my mind it is better to use TPL. DownloadXmle should be asynchronous method which is returning Task<T> or just Task. It will help you to have better resources utilization and will give you powerful tool for your task. Let's look at your method implementation in that case:
public async Task DownloadXmleAsync(string customer)
{
...
}
Next when you will call you method you should save returning task somewhere:
Task taskAbc = DownloadXmleAsync("ABC");
When you will get new request for this customer you should do next:
taskAbc = taskAbc.ContinueWith(prevTask => DownloadXmleAsync("ABC"));
ContinueWith will schedule your next call and will run it only after first request will be finished. Second task will run in any case. taskAbc will be a link to a second task. Every time you will get new request it will scheduled.
I am using background worker to execute an "Import" web-service call;
This import operation call can take about 5 seconds to complete, so i was wondering how i could best visually entertain the user. I have seen that most progress bars are more or less used in loop operations where they get updated per object processed. In my doWorker, i just have the webservice call;
Something like :
Details importinfo = (Details)sender;
e.Result = WebService.ImportMe(importinfo);
So will it be smart to have a progress bar in such an operation or some animation while the user waits for completion ? How can i best approach this ?
When you have no idea how long it will take and/or at what "point" of the operation you are you can set the Style to ProgressBarStyle.Marquee.
I am currently working on a page where a user can upload a large file and enter a amount line numbers. Then my function splits the large file into smaller ones depending of lines numbers the user wants.
Anyway let's say I end up creating 100 files for an original file of 10,000 records and the user wants 100 records per file.
I am looking for a way to display on my screen the number of files created so far while the function is still running ?
protected void SplitFileBtn_Click(object sender, EventArgs e)
{
var directory = new DirectoryInfo(fileName);
Empty(directory);
var fileSize = FileSizeInput.Text;
_sxw.Start();
SplitFile(100, fileName);
}
Use a BackgroundWorker to do the work. This will take care of performing the long running work in a non-UI thread, so as to not block the UI, and provides convenient means of updating the UI with the progress of the work as well as updating it when the work is completed.
Simply create a worker, do the work in a DoWork event hander, call UpdateProgress from that handler when you finish a file, and then update the UI with the current progress in the ProgressUpdated event handler. There are many examples of following this pattern on the MSDN page for BackgroundWorker, and elsewhere all around the web.
Here is how I am trying to do:
void Fetch()
{
//Code To Fetch Data
}
protected void btn_Click(object sender, EventArgs e)
{
lblSatus.Text = "Fetching Data...";
Thread t = new Thread(Fetch);
t.Start();
t.Join();
lblSatus.Text = "Got Data";
}
But on click of button it directly display GotData.
Any idea what I am doing wrong here.
Thanks
After the t.Start(); you need something that does a check ...along the lines of:
while (!t.Completed) // pseudo
{
// wait
Thread.Sleep(10);
}
Otherwise, the thread spins up and begins execution while the Main thread simply falls through.
I think you're misunderstanding the relationship between threads on the server-side when processing an ASP.NET request, and the experience on the browser-side. Specifically, for a given HttpRequest (in your example, the Request is a postback, which triggers the btn_Click event), there will be one and only one Response. This is true, regardless of what thread-manipulation you're doing on the server-side.
In your example, it looks like you're expecting the server to respond to the browser, with lblSatus's value as "Fetching data...". Then a little later when the operation has completed, the server would "respond" to the browser again, with lblSatus's value as "Got Data". This will not work, due to the "handshake" nature of Http communication: one request will result in one response (and thus, only one value for lblSatus).
The thing you're trying to do (give the end user a logical "progress bar" during a long-running operation) is a common requirement. Unfortunately, I know of no easy built-in way to do this in ASP.NET. I suspect most people do it via a polling model: the browser initiates the action, the server kicks it off in some sort of asynchronous fashion that does NOT delay the response being sent back to the browser. Then the browser periodically (via javascript, most likely) reaches back to the server to get an update on the operation's progress.