Resolved Throw exception to the caller function

Anonymous

Well-known member
Joined
Sep 29, 2020
Messages
94
Programming Experience
Beginner
I am writing a winform application that reads a large excel file, does some processing, and writes output in some other excel file. While the main form is doing its task, my app shows a please wait form. My issue is that when an exception is occurring in the processExcel Method, the catch block is not throwing that exception to the caller function, i.e, BtnClick(). Is it because the exception is thrown in a different thread?

I want only the caller function to handle all the exceptions, so that only one message is displayed and I also want to close the Please wait form when an exception occurs. I think I can only do that in the BtnClick().
Currently, when I run the .exe and an exception occurs, the pleasewait form remains open and I get a message an unhandled exception has occurred.

C#:
private async Task btnClick()
{
    try
    {
        cts = new CancellationTokenSource();

        PleaseWait pleasewait = new PleaseWait();
        pleasewait.Closed += PleaseWait_Closed;
 
        pleasewait.Show();

try{
        // Perform your long-running task asynchronously
        await Task.Run(() => ProcessBookstoreExcel(cts.Token));
}
catch(OperationCanceledException)
{
       cancel = true;
        pleasewait.Close();
       //showmessage
}
catch(Exception ex)
{
        pleasewait.Close();
       //showmessage
}
        pleasewait.Closed -= PleaseWait_Closed;

        pleasewait.Close();

        if(!cancel)
        MessageBox.Show("Processing Complete!");
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        cts.Dispose();

        cts = null;
    }
}

private void PleaseWait_Closed(object sender, EventArgs e) => cts.Cancel();

private void ProcessBookstoreExcel(CancellationToken cancellationToken)
{

try{

    string path = TxtBox.Text;
    ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
    var records = new List<BookRecord>();

    using (var package = new ExcelPackage(new FileInfo(path)))
    {
        ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
        int rowCount = worksheet.Dimension.Rows;

        for (int row = 2; row <= rowCount; row++) // Skip header row
        {
            cancellationToken.ThrowIfCancellation();

            records.Add(new BookRecord
            {
                LineNumber = row,
                ISBN = worksheet.Cells[row, 1].Text,
                Title = worksheet.Cells[row, 2].Text,
                Stock = int.Parse(worksheet.Cells[row, 3].Text),
                Price = decimal.Parse(worksheet.Cells[row, 4].Text),
                PublisherID = int.Parse(worksheet.Cells[row, 5].Text),
                PublisherName = worksheet.Cells[row, 6].Text
            });
        }
    }

    var discrepancies = new List<Discrepancy>();
    var groupedRecords = new Dictionary<string, Dictionary<string, (decimal Price, int Stock)>>();

    foreach (var record in records)
    {
        cancellationToken.ThrowIfCancellation();
 
        var publisherKey = record.PublisherID.ToString();
        var isbnKey = record.ISBN;

        if (!groupedRecords.ContainsKey(publisherKey))
        {
            groupedRecords[publisherKey] = new Dictionary<string, (decimal Price, int Stock)>();
        }

        if (!groupedRecords[publisherKey].ContainsKey(isbnKey))
        {
            groupedRecords[publisherKey][isbnKey] = (record.Price, record.Stock);
        }
        else
        {
            var existing = groupedRecords[publisherKey][isbnKey];
            if (existing.Price != record.Price || existing.Stock != record.Stock)
            {
                discrepancies.Add(new Discrepancy
                {
                    LineNumber = record.LineNumber,
                    Publisher = record.PublisherName,
                    Title = record.Title
                });
            }
        }
    }

    WriteDiscrepancies(discrepancies);
}
catch(OperationCanceledException)
{
throw;
}
catch(Exception ex)
{
throw;
}
}

private void WriteDiscrepancies(List<Discrepancy> discrepancies)
{
    try{
    var outputPath = Path.Combine(Path.GetDirectoryName(filePath), "discrepancies.xlsx");

    using (var package = new ExcelPackage())
    {
        var worksheet = package.Workbook.Worksheets.Add("Discrepancies");
        worksheet.Cells[1, 1].Value = "LineNumber";
        worksheet.Cells[1, 2].Value = "Publisher";
        worksheet.Cells[1, 3].Value = "Title";

        for (int i = 0; i < discrepancies.Count; i++)
        {
            worksheet.Cells[i + 2, 1].Value = discrepancies[i].LineNumber;
            worksheet.Cells[i + 2, 2].Value = discrepancies[i].Publisher;
            worksheet.Cells[i + 2, 3].Value = discrepancies[i].Title;
        }

        package.SaveAs(new FileInfo(outputPath));
    }
    }
    catch
    {
        throw;
    }
}
 
Last edited:
I have modified the code. I figured out how to catch exceptions from a different thread. But now my new issue is that after the exception is caught in the catch block. of BtnClick() Then it does not stop execution. It displays the exception and then continues with the other lines after the catch block. How do I stop the execution.
 
If it's not working then you did it wrong. If you don't show us what you're doing, we can't see what's wrong with it. You say that you modified the code but didn't show us how.
 
If it's not working then you did it wrong. If you don't show us what you're doing, we can't see what's wrong with it. You say that you modified the code but didn't show us how.

The modified code is the quesiton. I edited the question and replaced the original code with the modified code. I wrapped the
C#:
await Task.Run(() => ProcessBookstoreExcel(cts.Token));
in try/catch block. And to stop the execution of the code after the catch block is hit in the BtnClick(), I added return in each catch block.
 
Don't edit your posts unless you make a mistake. If you want to add new information, add it in a new post. A Q&A site like StackOverflow requires a single source of truth, so editing a question is what you do there. On forums like this, the posts should form a timeline. If the question in the first post refers to code that is no longer included, the actual question now doesn't make sense.
 
Given something like this:
C#:
void Fail()
{
    throw new SomeException();
}

void DoIt()
{
    try
    {
        Fail();
    }

    catch (SomeException ex)
    {
        MessageBox.Show("It's smee.");
        return;
    }

    finally
    {
        MessageBox.Show("It's smee again.");
    }

    MessageBox.Show("Guess who's back?");
}

You should see "It's smee" and "It's smee again.", but not "Guess who's back?".
 
Back
Top Bottom