3

I'm trying to run an ATM Simulation in C# with Windows Forms that can have more than one instance of an ATM machine transacting with a bank account simultaneously.

The idea is to use semaphores/locking to block critical code that may lead to race conditions.

My question is this:

How can I run two Forms simultaneously on separate threads? In particular, how does all of this fit in with the Application.Run() that's already there?

Here's my main class:

public class Bank
{
    private Account[] ac = new Account[3];
    private ATM atm;


    public Bank()
    {
        ac[0] = new Account(300, 1111, 111111);
        ac[1] = new Account(750, 2222, 222222);
        ac[2] = new Account(3000, 3333, 333333);


        Application.Run(new ATM(ac));


    }

    static void Main(string[] args)
    {
        new Bank();
    }
}
...that I want to run two of these forms on separate threads...

public partial class ATM : Form
{
    //local reference to the array of accounts
    private Account[] ac;

    //this is a reference to the account that is being used
    private Account activeAccount = null;

    private static int stepCount = 0;

    private string buffer = "";

    // the ATM constructor takes an array of account objects as a reference
    public ATM(Account[] ac)
    {
        InitializeComponent();  //Sets up Form ATM GUI in ATM.Designer.cs
        this.ac = ac;
    }
...

I've tried using

Thread ATM2 = new Thread(new ThreadStart(/*What goes in here?*/));

But what method do I put in the ThreadStart constructor, since the ATM form is event-driven and there's no one method controlling it?

EDIT:

I've tried replacing Application.Run(new ATM(ac)); with

ATM atm1 = new ATM(ac);
ATM atm2 = new ATM(ac);
Thread ATM2_T = new Thread(new ThreadStart(atm1.Show));
Thread ATM1_T = new Thread(new ThreadStart(atm2.Show));
ATM1_T.Start();
ATM2_T.Start();

in the Bank constructor. Nothing is displayed and the program drops-off the end of the Main() function.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Calum Murray
  • 1,102
  • 3
  • 12
  • 20

3 Answers3

9

Here's what I think you need to do:

Thread ATM2 = new Thread(new ThreadStart(ThreadProc));
ATM2.Start();

It calls this method:

private void ThreadProc()
{
    var frm = new ATM();
    frm.ShowDialog();
}
Brad Rem
  • 6,036
  • 2
  • 25
  • 50
1

The above is unsafe code

Please find the threadsafe code:

Thread ATM2 = new Thread(new ThreadStart(ThreadProc));
ATM2.Start();

It calls this method:

private void ThreadProc()
{
    if(InvokeRequired)
    {
        this.Invoke(new Action(() => CreateAndShowForm()));
        return;
    }
    CreateAndShowForm();

}

private void CreateAndShowForm()
{
    var frm = new ATM();
    frm.ShowDialog();
}
René Vogt
  • 43,056
  • 14
  • 77
  • 99
TsunamiCoder
  • 120
  • 1
  • 12
0

In Bank.Main(), try relpacing Application.Run(new ATM(acc)) with new ATM(acc).Show(). You can use the Form.Show() method as many times as you want. If I recall correctly, the application will close when all forms are closed (although I could be mistaken--try this with the VS debugger)

hehewaffles
  • 582
  • 5
  • 17