I want to send a progress bar that is available on my form to a function to display the progress of the operation of that function and finally return true if everything is fine and return false if else
The operation inside the SaveBadCustomerMustStayMasdoodExcelFile
function is executed asynchronously so as not to interfere with the execution of other operations.
When the program runs and the compiler calls the line _ProgressBar.Invoke((MethodInvoker)(() => {_ProgressBar.Value = Convert.ToInt32(i);}));
Inside the badCustomers.SendToDB(progressBar_BadCustomers)
function, there is no feedback and the program seems to be stuck in an infinite loop.
But if the output of the SaveBadCustomerMustStayMasdoodExcelFile
function is defined as void, everything works fine.
My code when the system hangs:
In Button:
private void btn_ChoiceBadCustomersFile_Click(object sender, EventArgs e)
{
try
{
DialogResult dialogResult = MessageBox.Show("message", "title",
MessageBoxButtons.YesNo);
if ((dialogResult == DialogResult.Yes))
{
bool result = false;
try
{
result = GetDataFromExcelFile.SaveBadCustomerMustStayMasdoodExcelFile(
progressBar_BadCustomers).Result;
}
catch
{
result = false;
}
if (result)
{
//code...
}
}
}
catch
{
//code...
}
}
Code In GetDataFromExcelFile.SaveBadCustomerMustStayMasdoodExcelFile(...)
public static class GetDataFromExcelFile
{
public async static Task<bool> SaveBadCustomerMustStayMasdoodExcelFile(
DevComponents.DotNetBar.Controls.ProgressBarX progressBar_BadCustomers)
{
try
{
PoomaDbAppEntities DB10 = new PoomaDbAppEntities();
IQueryable<tbl_BadCustomers> dt = null;
MyExcelWorkSpace _excelApp = new MyExcelWorkSpace();
MyExcelWorkSpace.badCustomers badCustomers = new MyExcelWorkSpace
.badCustomers();
string path = badCustomers.select();
if (path != String.Empty)
{
if (badCustomers.Open(path))
{
try
{
await Task.Run(() => { dt = badCustomers
.SendToDB(progressBar_BadCustomers); });
return true;
}
catch
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
catch
{
return false;
}
}
}
And In badCustomers.SendToDB(...) :
public class badCustomers : ExcelFile, IStartWorkWithExcelFile<tbl_BadCustomers>
{
//code
public IQueryable<tbl_BadCustomers> SendToDB(DevComponents.DotNetBar
.Controls.ProgressBarX _ProgressBar)
{
try
{
//code
_ProgressBar.Invoke((MethodInvoker)(() => {
_ProgressBar.Value = Convert.ToInt32(i); }));
}
catch
{
//code
}
}
IQueryable<tbl_BadCustomers> dt = DB10.tbl_BadCustomers.Select(i => i);
return dt;
}
}
If the SaveBadCustomerMustStayMasdoodExcelFile
function is defined as below, the program works, but I need to know if an error has occurred or not.
public async static void SaveBadCustomerMustStayMasdoodExcelFile(
DevComponents.DotNetBar.Controls.ProgressBarX progressBar_BadCustomers)
{
//code
}
If the SaveBadCustomerMustStayMasdoodExcelFile
function is defined as below, the program works, but I need to know if an error has occurred or not.
public async static void SaveBadCustomerMustStayMasdoodExcelFile(
DevComponents.DotNetBar.Controls.ProgressBarX progressBar_BadCustomers)
{
//code
}
CodePudding user response:
there is no feedback and the program seems to be stuck in an infinite loop.
This is because the code is using Result
; full details on my blog.
To solve this, you want to avoid async void
(i.e., for SaveBadCustomerMustStayMasdoodExcelFile
); async void
is intended for event handlers, so you can make btn_ChoiceBadCustomersFile_Click
an async void
method. Everything else should use await
and async Task
.
As far as the Progress goes, I echo the recommendations in the comments: IProgress<T>
with Progress<T>
makes your code cleaner (e.g., no Invoke
necessary).