如何在c#中实现这个多线程场景
本文关键字:多线程 实现 | 更新日期: 2023-09-27 18:06:46
我想这样做:
function void DoSomething(string path){
try {
DownloadDataFromWebSite(path)
}catch(OtherUserLoggedInUsingSameAcountException ex){
If (I am the first thread that get here){
Login();
}else{
Wait for the first thread to finish Login();
}
DownloadDataFromWebSite(path);
}
}
我有一个集合,我将像这样命名它:
APathCollection.AsParallel().ForAll(DoSomething)
请帮助我,我该如何实现这个模式?这可能吗?
PS:我省略了错误计数器,请假定它不会进入无限循环。
更新:我已经更新了代码,以反映我在@IPValverde请求上真正做的事情。
好的,您提供了更多关于您的场景的信息。我认为你可以创建第二个锁,指示是否有一个线程正在登录。
下面是一个片段:
public class Program
{
public static void Main()
{
new Program().Execute();
}
public void Execute()
{
// lock objects
this.fixErrorLock = new object();
this.isLoggingInLock = new object();
var objectsToIterate = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
objectsToIterate.AsParallel().ForAll(this.DoWork);
}
private object isLoggingInLock;
private object fixErrorLock;
private bool isLoggingIn;
public bool IsThereAnyThreadLoggingIn()
{
lock (this.isLoggingInLock)
{
// If no thread is logging-in, the one who asked is going to log-in
if (!this.isLoggingIn)
this.isLoggingIn = true;
return this.isLoggingIn;
}
}
public void DoWork(int myParam)
{
try
{
if (myParam % 4 == 0)
throw new Exception();
}
catch (Exception ex)
{
// Is the equivalent of 'is the first thread to hit here?'
bool canLogIn = this.IsThereAnyThreadLoggingIn();
// Every thread with error will stop here
lock (fixErrorLock)
{
// But only the first one will do the login process again
if (canLogIn)
{
// Inside the login method the variable responsible for the 'isFirstThread' is restored to false
this.LogIn();
}
}
this.DoWork(myParam-1);
}
}
public void LogIn()
{
Thread.Sleep(100);
lock (this.isLoggingInLock)
{
// The login is done
this.isLoggingIn = false;
}
}
}
你可以看到这个例子在这里运行:https://dotnetfiddle.net/SOXxO9
当您谈论线程安全时,资源是重要的。
所以首先读一下锁,特别是关于临界区的部分。
然后,在FixparticularException
方法中为每个"逻辑"资源创建一个锁,这样就可以了。如果您提供一些细节,我可以更明确地为您编写代码,这里是要点:
private bool _IsFixed;
public void DoSomething(int x)
{
try
{
DoWork(x)
}
catch (ParticularException pex)
{
FixParticularException(pex);
}
DoSomething(x);
}
private void FixParticularException (ParticularException pex)
{
lock (_resource1Lock)
{
if (_IsFixed)
return;
// fix it
_IsFixed = true;
}
}