Putting event handler codes inside DoWork delegate for asynchronous multi-threaded calculations
-
I have the following code for getting data and paginating them inside the DataGrid:
private void dataPager\_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args) { List data; using (var \_sqliteContext = new SQLiteContext()) { data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList(); } dataPager.LoadDynamicItems(args.StartIndex, data); //resetting cache for all pages. (dataPager.PagedSource as PagedCollectionView).ResetCache(); }
Now, I want to use background worker to do calculation in an another thread. I make the following changes:
private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = false;worker.DoWork += worker\_DoWork; worker.RunWorkerAsync(); }
void worker_DoWork(object sender, DoWorkEventArgs e)
{
List data;
using (var _sqliteContext = new SQLiteContext())
{
data = _sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList();
}
dataPager.LoadDynamicItems(args.StartIndex, data);
//resetting cache for all pages.
(dataPager.PagedSource as PagedCollectionView).ResetCache();
}But, worker_DoWork does not have any overload. I cannot pass args to worker_DoWork How can I solve it?
The
DoWorkEventArgs
class includes an Argument Property[^] You can set that to an instance of any class (or struct) to pass whatever you need in. It also contains a Result[^] property for passing completed data back to the caller via the RunWorkerCompleted Event[^]"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
-
The
DoWorkEventArgs
class includes an Argument Property[^] You can set that to an instance of any class (or struct) to pass whatever you need in. It also contains a Result[^] property for passing completed data back to the caller via the RunWorkerCompleted Event[^]"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
-
The
DoWorkEventArgs
class includes an Argument Property[^] You can set that to an instance of any class (or struct) to pass whatever you need in. It also contains a Result[^] property for passing completed data back to the caller via the RunWorkerCompleted Event[^]"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
I used the following code for getting data from SQLite:
private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
{
List list = new List()
{
int.Parse(args.StartIndex.ToString()),
int.Parse(args.PageSize.ToString())
};BackgroundWorker worker = new BackgroundWorker(); worker.WorkerReportsProgress = false; worker.DoWork += worker\_DoWork; worker.RunWorkerAsync(list); } void worker\_DoWork(object sender, DoWorkEventArgs e) { List value = (List)e.Argument; List data; using (var \_sqliteContext = new SQLiteContext()) { data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(value\[0\]).Take(value\[1\]).ToList(); } this.Dispatcher.Invoke(() => { dataPager.LoadDynamicItems(value\[0\], data); //resetting cache for all pages. (dataPager.PagedSource as PagedCollectionView).ResetCache(); }); }
There is no runtime error but the table in the UI is empty.
-
Is it possible to pass more than one instance of any class? Do I need to use List in this case?
You can use any
object
- so anint
, aMyClass
, a collection ofIEnumerable
objects, an array ... literally anything you need to. Just be aware that you are multithreaded so you need to ensure thread safety if the argument data is going to be even looked at by two different threads, and that Control derived classes can only be accessed from the thread that created them (the UI thread). But you almost certainly knew that ... I added it for those other readers who are just getting started with threading."I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
-
I used the following code for getting data from SQLite:
private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
{
List list = new List()
{
int.Parse(args.StartIndex.ToString()),
int.Parse(args.PageSize.ToString())
};BackgroundWorker worker = new BackgroundWorker(); worker.WorkerReportsProgress = false; worker.DoWork += worker\_DoWork; worker.RunWorkerAsync(list); } void worker\_DoWork(object sender, DoWorkEventArgs e) { List value = (List)e.Argument; List data; using (var \_sqliteContext = new SQLiteContext()) { data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(value\[0\]).Take(value\[1\]).ToList(); } this.Dispatcher.Invoke(() => { dataPager.LoadDynamicItems(value\[0\], data); //resetting cache for all pages. (dataPager.PagedSource as PagedCollectionView).ResetCache(); }); }
There is no runtime error but the table in the UI is empty.
Start with the debugger and see what
data
contains before you start the Invoke."I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
-
Start with the debugger and see what
data
contains before you start the Invoke."I have no idea what I did, but I'm taking full credit for it." - ThisOldTony "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt AntiTwitter: @DalekDave is now a follower!
-
I have the following code for getting data and paginating them inside the DataGrid:
private void dataPager\_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args) { List data; using (var \_sqliteContext = new SQLiteContext()) { data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList(); } dataPager.LoadDynamicItems(args.StartIndex, data); //resetting cache for all pages. (dataPager.PagedSource as PagedCollectionView).ResetCache(); }
Now, I want to use background worker to do calculation in an another thread. I make the following changes:
private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = false;worker.DoWork += worker\_DoWork; worker.RunWorkerAsync(); }
void worker_DoWork(object sender, DoWorkEventArgs e)
{
List data;
using (var _sqliteContext = new SQLiteContext())
{
data = _sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList();
}
dataPager.LoadDynamicItems(args.StartIndex, data);
//resetting cache for all pages.
(dataPager.PagedSource as PagedCollectionView).ResetCache();
}But, worker_DoWork does not have any overload. I cannot pass args to worker_DoWork How can I solve it?
Your BackgroundWorker is going to go out of scope; I haven't used that pattern so if it gets "busy", it will be hard to tell, if at all.
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
-
I used the following code for getting data from SQLite:
private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
{
List list = new List()
{
int.Parse(args.StartIndex.ToString()),
int.Parse(args.PageSize.ToString())
};BackgroundWorker worker = new BackgroundWorker(); worker.WorkerReportsProgress = false; worker.DoWork += worker\_DoWork; worker.RunWorkerAsync(list); } void worker\_DoWork(object sender, DoWorkEventArgs e) { List value = (List)e.Argument; List data; using (var \_sqliteContext = new SQLiteContext()) { data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(value\[0\]).Take(value\[1\]).ToList(); } this.Dispatcher.Invoke(() => { dataPager.LoadDynamicItems(value\[0\], data); //resetting cache for all pages. (dataPager.PagedSource as PagedCollectionView).ResetCache(); }); }
There is no runtime error but the table in the UI is empty.
Could it be that in
worker_DoWork
your variabledata
is going out of scope when the function ends?The difficult we do right away... ...the impossible takes slightly longer.
-
I have the following code for getting data and paginating them inside the DataGrid:
private void dataPager\_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args) { List data; using (var \_sqliteContext = new SQLiteContext()) { data = \_sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList(); } dataPager.LoadDynamicItems(args.StartIndex, data); //resetting cache for all pages. (dataPager.PagedSource as PagedCollectionView).ResetCache(); }
Now, I want to use background worker to do calculation in an another thread. I make the following changes:
private void dataPager_OnDemandLoading(object sender, Syncfusion.UI.Xaml.Controls.DataPager.OnDemandLoadingEventArgs args)
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = false;worker.DoWork += worker\_DoWork; worker.RunWorkerAsync(); }
void worker_DoWork(object sender, DoWorkEventArgs e)
{
List data;
using (var _sqliteContext = new SQLiteContext())
{
data = _sqliteContext.Equipments.Include(x => x.CostCenter).Skip(args.StartIndex).Take(args.PageSize).ToList();
}
dataPager.LoadDynamicItems(args.StartIndex, data);
//resetting cache for all pages.
(dataPager.PagedSource as PagedCollectionView).ResetCache();
}But, worker_DoWork does not have any overload. I cannot pass args to worker_DoWork How can I solve it?
Assuming you have to call the
LoadDynamicItems
from within the event handler, moving the data-loading code to a background thread really won't accomplish anything. You'll still need to block in the event handler until the background thread has finished, so you'll be using two threads to do what you're currently doing with one. You'll also potentially run into issues if you're working in a framework with a concept of a "UI thread"; the control will most likely expect theLoadDynamicItems
method to be called from the UI thread, not a background thread, so you'll end up getting an exception.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
Assuming you have to call the
LoadDynamicItems
from within the event handler, moving the data-loading code to a background thread really won't accomplish anything. You'll still need to block in the event handler until the background thread has finished, so you'll be using two threads to do what you're currently doing with one. You'll also potentially run into issues if you're working in a framework with a concept of a "UI thread"; the control will most likely expect theLoadDynamicItems
method to be called from the UI thread, not a background thread, so you'll end up getting an exception.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer