下面所有代码只创建两个进程。虽然我需要创建 n 个进程来打开 Chrome 浏览器并基于 dtUser.Rows.Count
运行 OpenNRowsInData(user, pwd)
,因为这是动态的。
而且我不知道为什么 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();
}
}
最佳答案
And I don't know why OpenNRowsInData(user, pwd); always only get first rows.
我觉得你的第二个威胁太快了。在第一行完成之前,它将执行 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])
但是这次它会在stepRun
中的0
位置找到一个1
。对全部
永远不要返回调用 OpenNRowsInData
。
这就是为什么您只得到第一行的原因。
编辑 2:
如果你想在两个浏览器中同时执行它,你可以创建一个例程来执行 AllCase
和 this 这两种情况,你可以在 2 中运行单独的线程:
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();
}
您还可以将整个浏览器对象传递给该方法,然后将它进一步向下传递给 OpenNRowsInData
并在那里使用它
关于c# - 如何在 C# 中创建基于 DataTable.Rows.Count 的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38821739/