Advanced programming


If you have methods that require a longer calculation time, you can have them executed in a separate background thread. These background tasks are performed in business objects with the class gip.core.datamodel.ACBackgroundWorker, which is a derivative of System.ComponentModel.BackgroundWorker .

Every business object has the property that is defined in ACBSO. You can use this instance to start an asynchronous task by calling the RunWorkerAsync (object argument) method . Pass the name of the method to be executed asynchronously as a parameter. Example:"public ACBackgroundWorker BackgroundWorker"

BackgroundWorker.RunWorkerAsync("MyAsyncTask");

When the asynchronous task is started, the virtual method " BGWorkerDoWork " is called because it is connected as a callback method in the ACBSO class with the DoWork event of the background worker .

public virtual void BgWorkerDoWork(object sender, DoWorkEventArgs e)

Override this method and call your method there that is to be executed in this background thread. Example:

public override void BgWorkerDoWork(object sender, DoWorkEventArgs e)
{
base.BgWorkerDoWork(sender, e);
switch (e.Argument.ToString())
{
case "MyAsyncTask":
MyAsyncTask();
break;
}
}

void MyAsyncTask() { ... }

After your asynchronous task has been executed, the virtual method " BgWorkerCompleted " is called because it is connected as a callback method in the ACBSO class to the RunWorkerCompleted event of the background worker .

public virtual void BgWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

Here you can add the final logic:

public override void BgWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
base.BgWorkerCompleted(sender, e);

ACBackgroundWorker worker = sender as ACBackgroundWorker;
string command = worker.EventArgs.Argument.ToString();
if
(e.Error != null) { ... }

else if (e.Cancelled) { ... }
else {
if (command == "MyAsyncTask") { ... } }

}

 

You will ask yourself, why should I use the BackgroundWorker when there is asynchronous programming with async and wait ?

Yes, you can of course also program this with it, only the display of a progress via WPF progress bar is not possible with it. The ACBSO also supports them in this.


To show a progress dialog, call "ShowDialog" with the design name "Progress" (constant DesignNameProgressBar) after calling "RunWorkerAsync ()":

ShowDialog(this, DesignNameProgressBar);

The following dialog appears:

 

Initialize and change progress

You can initialize the progress bar and the current progress in your method that is to be executed in the background. In the example above, it would be the MyAsyncTask method:

void MyAsyncTask () 
{
CurrentProgressInfo.TotalProgress. ProgressText = "My progress text" ;
CurrentProgressInfo.TotalProgress. ProgressRangeFrom = 0;
CurrentProgressInfo.TotalProgress. ProgressRangeTo = 1000;
CurrentProgressInfo.TotalProgress.ProgressCurrent = 0;
for ( int i = 0; i <1000; i ++)
{
CurrentProgressInfo.TotalProgress. ProgressCurrent ++ ;
// Do some work
}
}

 CurrentProgressInfo is a property of ACBSO and is of the type "gip.core.datamodel. ProgressInfo ": 

public class ProgressInfo : INotifyPropertyChanged, IVBProgress
{
public TaskProgressInfo TotalProgress { get; }
public List<TaskProgressInfo> SubTaskList { get; }
}

ProgressInfo in turn consists of "gip.core.datamodel. TaskProgressInfo " instances. The "TotalProgess" property shows the overall progress and the "SubTaskList" list can show many more sub-progresses.

public class TaskProgressInfo : INotifyPropertyChanged
{
public int ProgressRangeFrom { get; set; }
public int ProgressRangeTo { get; set; }
public int ProgressCurrent { get; set; }
public string ProgressText { get; set; }
}

Before starting the task, define the area of ​​the progress bar with the ProgressRangeFrom and ProgressRangeTo properties. During execution, increment the ProgressCurrent property so that the progress bar in the dialog is updated.

 

Sub-progress

To display further progress bars for subtasks, use the " AddSubTask " method :

int rangeFrom = 0, rangeTo = 100;
ProgressInfo.AddSubTask("MySubTaskname", rangeFrom, rangeTo);

To update the current progress of a subtask, use the ReportProgress method :

void ReportProgress(string subTaskName, int? progressCurrent, string newProgressText = null)

You pass the task name in the first parameter. Pass null if you want to update the main progress bar.
In the second parameter you pass the current progress. At zero nothing is changed.
Pass the progress text in the third parameter. At zero nothing is changed.

// Sets the current progress of a subtask (ProgressCurrent of a instance in SubTaskList):
ProgressInfo.ReportProgress("MySubTaskname", mySubTaskCounter);
// Changes the progresstext of a subtask (ProgressText of a instance in SubTaskList):
ProgressInfo.ReportProgress("MySubTaskname", null, "Completed");
// Changes the total progress (TotalProgress.ProgressCurrent):
ProgressInfo.ReportProgress(null, myMainCounter);
// Changes the progresstext of the main header (TotalProgress.ProgressText):
ProgressInfo.ReportProgress(null, null, "Completed");

ReportProgess triggers the ProgressCurrent event  that is linked to the virtual method  from ACBSO. You can override this method if you are interested.
public virtual void BgWorkerProgressChanged(object sender, ProgressChangedEventArgs e)

 

Individual Design

If you do not like the  "Progress" design from ACBSO, you can display the dialog with your own design. Either you make a base class for all of your BSO's in which you overwrite the "Progress" design or you assign a new name. The default design uses the iPlus control " gip.core.layoutengine. VBProgressBar " to display:

 

Bind the ProgressRangeFrom property to the RangeBase.Minimum property,  ProgressRangeTo and RangeBase.Maximum, and ProgressCurrent to RangeBase.Value .