简体   繁体   中英

c# showing a process form seems to get stuck when performing a long running task

I am in the process of creating a POS system using C# and WinForms.

I am using a form with some text and an image to indicate when a long running process is performed, like sales printing and DB update after the sale. But when I do that, only the AjaxLoader form is showing and it's not calling the update functions below it.

This is my code.

public void completeSale()//invoked on Sell button
{
    
    loader = new AjaxLoader();//this is a form
    loader.label1.Text = "Printing...";
    ThreadStart threadStart = new ThreadStart(Execution);
    Thread thread = new Thread(threadStart);
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
}

private void Execution()
{
    this.Invoke((MethodInvoker)delegate { loader.ShowDialog(this); });
    Application.DoEvents();

    update_sale("Sold");//method not getting called at all

    this.Invoke((MethodInvoker)delegate { loader.Dispose(); });
}

This is my Ajax loader form that I need to display, that is supposed to block my POS form. So upon finishing the printing (doing background task) I need to close the loader.

Ajax 加载器

The problem is that the lines

Application.DoEvents();
update_sale("Sold");//method not getting called at all

is never reached.

What am I doing wrong?

The .ShowDialog() on a form is a blocking call, so your code will wait until the form that is shown as dialog is .Closed()

I would also recommend using using async Task as this makes working with Threads much much easier!

I've changed your code to show this.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        await completeSale();
    }

    AjaxLoader loader = null;
    public async Task completeSale()//invoked on Sell button
    {
         //for info, this is how I set up AjaxLoader form properties in the designer.
         loader = new AjaxLoader();
         loader.label1.Text = "Printing...";
         loader.TopMost = true;
         loader.WindowState = FormWindowState.Normal;
         loader.StartPosition = FormStartPosition.CenterParent;
         loader.ShowInTaskbar = false;
         loader.ControlBox = false;
         loader.FormBorderStyle = FormBorderStyle.None;
        //loader.PointToClient(this.DesktopLocation);

        await Execution();   
    }

    private async Task Execution()
    {
        
        if (loader.InvokeRequired)
            this.Invoke((MethodInvoker)delegate { loader.Show(this); });
        else
            loader.Show(this);
        //Application.DoEvents();

        await update_sale("Sold");

        if (loader.InvokeRequired)
            this.Invoke((MethodInvoker)delegate { loader.Close(); });
        else
            loader.Close();
        
    }

    private async Task update_sale(string v)
    {
        //long running process like printing etc..
        await Task.Delay(3000);
    }
}

this will do something like this:

在此处输入图片说明

On the AjaxLoader form I added a progress bar that is set to style = Marquee

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM