I need to call a stored proc that does quite a bit of work.
I want to be able to "fire and forget" e.g not wait for the response of the stored proc before moving onto the next record as that slows things down and I need to be moving quickly.
What is the best method of calling a stored proc in C# and NOT waiting for the result, returning a success status, and then moving onto the next record.
I'd like to be able to just quickly loop through my object list of selections and call some method that does the DB call without waiting for the response before moving to the next item in the loop.
It's using C# 4.5.
I was thinking about using something like
Parallel.ForEach(sqlRecordset.AsEnumerable(), recordsetRow =>
{
// get data for selection
// call DB to save without waiting for response / success/failure status
}
But I don't know if this is the best approach or not.
Ideas?
Thanks in advance for any help.
Parallel.ForEach is parallel but synchronous - it will wait for all its iterations to finish.
You may use TPL (Task Parallel Library) to achieve what you want:
foreach (var recordsetRow_doNotUse in sqlRecordset.AsEnumerable())
{
var recordsetRow = recordsetRow_doNotUse;
Task.Run(() => {
Console.WriteLine(recordsetRow);
/* or do whatever you want with it here */
});
}
Task.Run returns a task so if you need to do something when all of them are done you can put all of them in an array and then use Task.WhenAll to obtain a Task which will be complete when all iterations are complete, without blocking any threads.
P.S. I don't know what you mean by C# 4.5, probably .NET 4.5 which is C# 5. My sample code above won't work with earlier versions of C#.
The easier approach is using ADO.NET:
var cmd = new SqlCommand("storeProcName", sqlConnection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.BeginExecuteNonQuery();
Since you would like to iterate through each records, get some values and store it in the database and not wait for any record set, you could do something like below; Assuming you are using windows application and know threading;
foreach (DataRow row in DataTable.Rows) //you can use any enumerable object here
{
string s = row.Fields("name").ToString();
Thread t = new Thread(new ParameterizedThreadStart(SaveName));
t.IsBackground = true;
t.start(s);
}
public void SaveName(object s)
{
//your code to save the value in 's'
}
This way, you will not have to wait for the database to respond and every values will be saved. The threads will be destroyed as soon as it finish saving and processing your records..
Hope this helps.
Happy coding..!!
Related
I'm working on a C# winforms application.
I try to execute a code that return a huge data from database (Using LINQ with Entity Framework) on a new created Thread, and I show the data returned in DataGridView.
Code block :
GVentesEntities context=new GVentesEntities();
Thread t =new Thread(() =>
{
var R = context.Client.AsQueryable();
Invoke(new Action(() =>
{
dataGridView1.DataSource = R.ToList();
}));
});
t.Start();
The problem is after starting the Form the data load slowly in DataGridView, as I know that DataGridView runing on the main Thread.
How can I let DataGridView runing on another new Thread for fast loading data ? Or if you have any other solution I don't know about it.
Massive thanks in advance.
You're executing the query back on the UI thread. Don't do that. Call ToList() outside of the Invoke, and then you're only passing the results to the grid. Of course, there may still be performance issues with that, but that's a rather broad topic of dynamic data loading.
Multi-threaded GUI is very tricky, and rarely worth the trouble. Try to separate business logic from GUI instead, and make sure the GUI doesn't do too much unnecessary stuff. In general, if you want to show a lot of data in a component, you need to use e.g. a virtual grid - instead of building all the grid cells when you assign data to the DataSource, you only create them on demand (when they become visible etc.). Unlike, say, Delphi, this doesn't happen automatically with .NET's DataGridView - you need to write a bit of code.
You are right. If you have a WinForms application, and you need to do some lengthy calculations, it is a good idea to start a separate thread to do this. In the mean time your user interface thread is free to do other things, like react on buttons, update the display and show the progress of the lengthy calculations.
A fairly outdated method to do this, was to start the BackGroundWorker class. Although this method works fine, people nowadays tend to use async-await for this, because it is simpler to use.
Usually you see async methods when somewhere deep inside the procedure the thread must wait idly for another process to finish: fetch data from a database; write data to a hard disk; read information from the internet, etc. If you use async-await, then your thread won't wait idly, but goes up the call stack to see if one of the callers is not awaiting. This way your user interface will still be responsive, provided that the thread is not busy doing calculations.
The standard method of async-await in WinForms is something like this:
private async void Button1PressedAsync(object sender, ...)
{
Button button = (Button)sender;
button.Enabled = false;
this.ShowProgress();
// Start the Task, if you can do something else, don't await yet
Task<string> taskFetchData = this.FetchDataAsync();
DoSomethingElse();
// wehtn you need the result of the task: await for it
string fetchedData = await taskFetchData;
this.ShowFetchedData(fetchedData);
this.HideProgress();
button.Enabled = true;
}
private async Task<string> FetchDataAsync()
{
using (var textReader = System.IO.File.OpenText(this.FileName))
{
return await textReader.ReadToEndAsync();
}
}
What we see here:
Every function who wants to use async-await must be declared async
Return Task<TResult> instead of TResult, return Task instead of void. Only exception: event handlers return void instead of Task: no one will have to await an event handler. In Forms you usually see them as button clicks, mouse clickes, menu selections etc.
Start the async task, if you don't need the result immediately, don't await yet,
but do other useful stuff.
Only when you need the result of the task, or at last just before you return await the task, so you are certain that the task is finished when you are finished. Alternative: return the task and let your caller await it.
Because the thread that returns after the await has the same "context", this thread can be regarded as the UI thread: it can update user interface elements. No need for IsInvokeRequired etc.
Back to your question
You want to keep you UI responsive while the data is being fetched from the database. If the database management system can do most of the work, you are lucky, a simple async-await is enough.
It depends a bit on the method that you use to communicate with the database. You will have to search for async methods. I'll give an example using SQL:
private async Task<List<Order>> FetchOrderOfCustomer(int customerId)
{
const string sqlText = "SELECT Id, OrderDate, ... FROM Customers"
+ "WHERE CustomerId = #CustomerId";
List<Order> orders = new List<Order>();
using (var dbConnection = new SQLiteConnection(this.dbConnectionString))
{
using (var dbCommand = dbConnection.CreateCommand())
{
dbCommand.CommandText = sqlText;
dbCommand.Parameters.AddWithValue("#CustomerId", customerId);
dbConnection.Open();
using (SQLiteDataReader dbReader = await dbCommand.ExecuteReaderAsync())
{
while (await dbReader.ReadAsync())
{
var order = new Order
{
Id = dbReader.GetInt64(0),
...
};
orders.Add(forder);
}
}
}
}
return orders;
}
Most of the work is done by the Database management system. The only work that you do is copying the fetched data to Order and adding it to the List.
Although this can be optimized a little, if you use a method like this, your user interface will be quite responsive. For instance if you click a button to update the datagridview:
private async void ButtonUpdate_Clicked(object sender, ...)
{
this.buttonUpdate.Enabled = false;
this.ProgressBar.Value = this.ProgressBar.Minimum;
this.ProgressBar.Visible = true;
// Start the task to fetch the data, don't await for the result yet:
var taskFetchOrders = FetchOrdersOfCustomer(this.CustomerId);
// while the data is being fetched, which takes half a minute,
// show some progress.
while (!taskFetchOrders.Completed)
{
ProgressBar.PerformStep();
await Task.Delay(TimeSpan.FromSeconds(0.5));
}
List<Order> fetchedOrders = taskFetchOrders.Result;
this.UpdateDataGridView(fetchedOrders);
// clean up the mess:
this.progressBar.Visible = false;
this.buttonUpdate.Enabled = true;
}
Here you see that I don't await for the results of the task. I need to do something else: I need to update the ProgressBar. If your task is less than a few seconds, I wouldn't bother and just await taskFetchOrders.
Because I await Task.Delay(...), my user interface is still responsive: it can react on other buttons, resizes, show dialog boxes, update progress bars etc. Every half second the Delay task is completed. It checks whether taskFetchOrders is completed, and if not it updates the progress bar and Delays again.
Hope this has given you some insight in how to use async-await in order to keep your application responsive.
I have the following scenario, a timer every x minutes:
download an item to work from a rest service (made in php)
run a process batch to elaborate item
Now the application is fully functional, but I want to speedup the entire process downloading another item (if present in the rest service) while the application is processing one.
I think that I need a buffer/queue to accomplish this, like BlockingCollection, but I've no idea how to use it.
What's the right way to accomplish what I'm trying to do?
Thank you in advance!
What you can do is create a function which checks for new files to download. Have this function start as its own background thread that runs in an infinite loop, checking for new downloads in each iteration. If it finds any files that need downloading, call a separate function to download the file as a new thread. This new download function can then call the processing function as yet another thread once the file finishes downloading. With this approach you will be running all tasks in parallel for multiple files if needed.
Functions can be started as new threads by doing this
Thread thread = new Thread(FunctionName);
thread.start();
Use Microsoft's Reactive Framework (NuGet "System.Reactive"). Then you can do this:
var x_minutes = 5;
var query =
from t in Observable.Interval(TimeSpan.FromMinutes(x_minutes))
from i in Observable.Start(() => DownloadAnItem())
from e in Observable.Start(() => ElaborateItem(i))
select new { i, e };
var subscription =
query.Subscribe(x =>
{
// Do something with each `x.i` & `x.e`
});
Multi-threaded and simple.
If you want to stop processing then just call subscription.Dispose().
I am inside a threat updating a graph and I go into a routine that makes a measurement for 4 seconds. The routine returns a double. What I am noticing is that my graph stops showing activity for 4 seconds until I am done collecting data. I need to start a new thread and put the GetTXPower() activity in the background. So in other words I want GetTXPower() and the graph charting to run in parallel. Any suggestions?
here is my code:
stopwatch.Start();
// Get Tx Power reading and save the Data
_specAn_y = GetTXPower();
_pa_Value = paData.Start;
DataPoint.Measurement = _specAn_y;
//Thread.Sleep(50);
double remaining = 0;
do
{
charting.stuff
}
uxChart.Update();
I suggest looking into Task Parallel Library.
Starting with the .NET Framework 4, the TPL is the preferred way to write multithreaded and parallel code.
Since you also need the result back from GetTXPower, I would use a Task<double> for it.
Task<double> task = Task.Factory.StartNew<double>(GetTXPower);
Depending on when you need the result, you can query if the task has completed by checking task.IsCompleted or alternatively block the thread and wait for the task to finish by calling task.Wait(). You can fetch the result through task.Result property.
An alternative would be to add a continuation to the initial task:
Task.Factory.StartNew<double>(GetTXPower).ContinueWith(task =>
{
// Do something with the task result.
});
Make a void method (I'll call it MeasureMentMethod) that collects the data. The create a Thread using the following code:
Thread MeasurementThread = new Thread(new ThreadStart(MeasurementMethod));
You can then run the thread with
MeasurementThread.Start();
And if your Thread has something like this:
while(true){
//Run your code here
Thread.Sleep(100);
}
Then you can just start it at the beginning, and it will just keep collecting data.
So, you would have your main thread that would update the chart, and you would start the thread that would get the data on the side.
I'm putting together a simple C# app where a user types commands into a "command bar" and the results are fetched in real time.
For example I could type, google stackoverflow, and it sends an API call off to google, fetches each of the results and displays them in the ui.
Currently I fire off the "search" method if a user pauses for more than 1/4 of a second on typing, so if you paused in the middle it could fire google stack and google stackoverflow.
Now in reality the api is doing a (rather slow) database query and this causes the ui to lock up while the first search completes, before it tries to start on the second search.
Is there a simple (C# 4.0) way to run the search call in a separate thread that I can then cancel/abort if the user continues typing?
e.g.
Task<string> thread;
string getSearchResults(string input) {
... Do some work ...
}
string userPaused(string search) {
if(this.thread.isRunning()) this.thread.Kill();
this.thread = new Task<String>(getSearchResults(string input);
return this.thread.result();
}
I've looked at the Tasks api and it doesn't look as if you can kill a task in the middle of work, it suggests using a while look and passing a shouldStop boolean, however during an API call to download the results there is no while loop.
The Threading documentation however points you to tasks if you need to get the return value.
What you may do with Tasks is to create them, and then cancel when not needed any more. If you can't cancel operation you are doing (like database query) - you can always cancel before results get returned. Your code may be something like this (not tested, just a draft):
var tokenSource2 = new CancellationTokenSource();
CancellationToken ct = tokenSource2.Token;
var task = Task.Factory.StartNew(() =>
{
ct.ThrowIfCancellationRequested();
var result = Database.GetResult(); // whatever database query method you use.
ct.ThrowIfCancellationRequested();
return result;
}, tokenSource2.Token);
So as you can see it will query database and return value when no cancellation requested, but if you will try to cancell the task - it will not return value but rather throw OperationCanceledException you need to catch. For details visit MSDN Task Cancellation, but I think this should give you an idea. Don't worry about big task number - if your query is not very slow it won't matter - user will not be able to trigger so many searches. If you have asynchronous way of querying database - you can improve this code a bit more, but that also shouldn't be too hard.
i have (want) to execute a search request to multiple sources.
Now i've done some multithreading in the past, but it was all fire and forget.
Now what i want to do, is to spin up 3 identical requests on 3 different objects, wait until they are all 'done' (and that gives me the first question: how do they say 'i'm done', and then collect all the data thet've sent me.
So in pseudo code i have this interface:
interface ISearch
SearchResult SearchForContent(SearchCriteria criteria)
So in code i create the three search services:
ISearch s1 = new SearchLocal();
ISearch s2 = new SearchThere();
ISearch s3 = new SearchHere();
And then call SearchForContent(SearchCriteria criteria) on all three of them, in a multihreaded / async way
and the they all come back to me with their SearchResult and after they are ALL done, i process their SearchResult objects.
I hope these lines of text kindof makes you get what is in my head :)
i'm working on a ASP.Net 3.5 C# project.
Create AutoResetEvent and pass them to WaitHandle.WaitAll()
There is an example here.
Basically:
1) You create an AutoResetEvent for each search and pass false to its constructor.
2) Create the threads and run search for each one and at the end, call Set on the AutoResetEvent in the finally block. It is very important that calling Set is done inside the finally block otherwise WaitAll() will be waiting indefinitely.
3) In the code right after you have spawned the threads, you call WaitHandle.WaitAll() and pass all those AutoResetEvent to it. This code will wait until all is finished.
Using tasks you could do a continuation like this:
Task[] t = new Task[2];
t[0] = Task.Factory.StartNew(() => { Thread.Sleep(1000); });
t[1] = Task.Factory.StartNew(() => { Thread.Sleep(2000); });
Task.Factory.ContinueWhenAll(t, myTasks => { Console.WriteLine("All done!"); });
Make an IEnumerable<ISearch>, and those items to it, and do .AsParallel().ForAll(...) on it.
Edit
ForAll won't return results, if you can change ISearch, give it a property for the results, then once the ForAll is done you can look at the results through the IEnumerable.
And yes, sorry, this is 4.0.