如何在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请求上真正做的事情。

如何在c#中实现这个多线程场景

好的,您提供了更多关于您的场景的信息。我认为你可以创建第二个锁,指示是否有一个线程正在登录。

下面是一个片段:

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;
    }
}