简体   繁体   中英

How to create n Object base on DataTable.Rows.Count in C#?

All code below only to create two processes. While I need to create n process to open Chrome browser and run OpenNRowsInData(user, pwd) based on dtUser.Rows.Count because this is dynamic.

And I don't know why OpenNRowsInData(user, pwd); always only get first rows.

I have a DataTable range from 1-7 rows.

Typically, I was usually using to create two objects.

static myObject[] browser = new myObject[] { 
          new myObject(Browsers.Chrome, 0), 
          new myObject(Browsers.Chrome, 0)
};

Thread t1, t2;

t1 = new Thread(new ThreadStart(AllCase))
{
    Name = "Thread1"
};
t1.Start();

t2 = new Thread(new ThreadStart(AllCase))
{
    Name = "Thread2"
};
t2.Start();

In class AllCase :

static int[] stepRun = { 0, 0 };
private void AllCase()
{
    int idx = int.Parse(Thread.CurrentThread.Name.Replace("Thread", "")) - 1;
    switch (stepRun[idx])
    {
        case 0:
            foreach (DataRow row in dtUser.Rows)
            {
                user = row["user"].ToString();
                pwd = row["pwd"].ToString();
                OpenNRowsInData(user, pwd);
            }
            break;
        case 1:
            ClickBuy();
            break;
    }
}

And in another, before I using parallel process. Currently, I don't want to use it.

Parallel.ForEach(
    dtUser.AsEnumerable(),
    items => OpenNRowsInData(items["user"].ToString(), items["pwd"].ToString()));

I want to get only columns user and pwd .

Tried with code, I tried to add a parameter in action() method like: action(string user, string pwd) .

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
    if (source == null) throw new ArgumentNullException("source");
    if (action == null) throw new ArgumentNullException("action");

    foreach (T item in source)
    {
        action(item);
    }
}

Updated:

Add class OpenNRowsInData(string username, string password) :

private void OpenNRowsInData(string username, string password)
{
    int idx = int.Parse(Thread.CurrentThread.Name.Replace("Thread", "")) - 1;
    try
    {
        browser[idx].DeleteAllCookies();
        browser[idx].GoToUrl(link);
        browser[idx].waittingID("txtUserName", 15);
        browser[idx].FindElementById("txtUserName").SendKeys(username);
        browser[idx].FindElementById("txtpassword").SendKeys(password);
        browser[idx].FindElementById("btnlogin").Click();
        stepRun[idx] = 1;
        AllCase();
    }
}

And I don't know why OpenNRowsInData(user, pwd); always only get first rows.

It seems for me that your second threat is too fast. Before the first can finish it will execute ClickBuy(); so only the first row can be processed.

try to do it one step after the other

AllCase(0, 0);
AllCase(1, 0);


private void AllCase(int case, int browserNr)
{
    switch (case)
    {
        case 0:
            foreach (DataRow row in dtUser.Rows)
            {
                user = row["user"].ToString();
                pwd = row["pwd"].ToString();
                OpenNRowsInData(user, pwd, browserNr);
            }
            break;
        case 1:
            ClickBuy();
            break;
    }
}

private void OpenNRowsInData(string username, string password, int browserNr)
{      
    try
    {
        browser[browserNr].DeleteAllCookies();
        browser[browserNr].GoToUrl(link);
        browser[browserNr].waittingID("txtUserName", 15);
        browser[browserNr].FindElementById("txtUserName").SendKeys(username);
        browser[browserNr].FindElementById("txtpassword").SendKeys(password);
        browser[browserNr].FindElementById("btnlogin").Click();
    }
}

If you want to do it for both browsers try running a loop on the array:

for(int j = 0; j < browser.Length;j++)
{
    AllCase(0, j);
    AllCase(1, j);
}

This time parallelisation would actually pay off. Because you could do the same stuff in both browsers at the same time, but it seems you should not do both AllCase - cases in the same browser at the same time, because they are consecutive

EDIT:

After your edit it seems that when you go in your loop the first time you set in OpenNRowsInData at the position 0

stepRun[idx] = 1;

and then call again

AllCase();

this time it will execute

    case 1:
        ClickBuy();
        break;

on the second iteration it will try again to switch on

switch (stepRun[idx])

but this time it will find a 1 on the position 0 in stepRun . For all and never go back in the case to call OpenNRowsInData . This is why you get only the first row.

EDIT 2:

if you want to do it at the same time in both browsers you can make a routine that executes the two cases of AllCase and this routine you can run in 2 separate threads:

public void doEverything(int browserIndex)
{
    AllCase(0, browserIndex);
    AllCase(1, browserIndex);
}

and start the threads like this:

for(int j = 0; j < browser.Length;j++)
{
    int brInd = j;
    Thread t= new Thread(()=>doEverything(brInd));
    t.Start();
}

you could also pass the entire browser object to the method and pass it further down to OpenNRowsInData and use it there

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