如何在C#中的DataTable.Rows.Count上创建n对象?

时间:2016-08-08 05:17:42

标签: c# multithreading linq datatable

以下所有代码仅用于创建两个进程。虽然我需要创建n流程来打开Chrome浏览器并根据OpenNRowsInData(user, pwd)运行dtUser.Rows.Count,因为这是动态的。

我不知道为什么OpenNRowsInData(user, pwd);总是只获得第一行。

我的DataTable范围是1-7行。

通常,我通常用来创建两个对象。

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();

在课程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;
    }
}

另一方面,在我使用并行进程之前。目前,我不想使用它。

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

我想只获得user列和pwd

尝试使用代码,我尝试在action()方法中添加参数,例如: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);
    }
}

更新

添加课程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();
    }
}

1 个答案:

答案 0 :(得分:1)

  

我不知道为什么OpenNRowsInData(user,pwd);总是只获得第一行。

对我来说,你的第二个威胁太快了。在第一次完成之前,它将执行ClickBuy();,因此只能处理第一行。

尝试在另一个

之后执行一步
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();
    }
}

如果您想为两个浏览器执行此操作,请尝试在阵列上运行循环:

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

这次并行化实际上会得到回报。因为您可以同时在两个浏览器中执行相同的操作,但似乎您不应同时执行两个AllCase - 相同浏览器中的情况,因为它们是连续的

修改

编辑完成后,当您第一次在OpenNRowsInData位置0

时进入循环时
stepRun[idx] = 1;

然后再次致电

AllCase();

这次它将执行

    case 1:
        ClickBuy();
        break;

在第二次迭代时,它将再次尝试打开

switch (stepRun[idx])

但这次会在1的{​​{1}}位置找到0。对全部 并且永远不会回到案件中致电stepRun。 这就是你只获得第一行的原因。

编辑2:

如果您想在两个浏览器中同时执行此操作,您可以创建执行OpenNRowsInData例程的两种情况的例程,您可以在2个单独的线程中运行:

AllCase

并启动这样的线程:

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

你也可以将整个浏览器对象传递给方法并将其进一步传递给for(int j = 0; j < browser.Length;j++) { int brInd = j; Thread t= new Thread(()=>doEverything(brInd)); t.Start(); } 并在那里使用