使用Datetime.Now的具有不同文件名的TPL

时间:2012-12-19 05:20:25

标签: .net datetime concurrency locking task-parallel-library

我正在使用任务将多个文件上传到sftp服务器。但目前正在发生的事情是,当多个任务并行执行时,会生成相同的“fileName”。我想确保每次都生成一个不同的文件名。

//Simplified version of my code:
processingTasks = 1000;
while (processingTasks > 0)
{
    processingTasks --;
    Task<string> task = Task<string>.Factory.StartNew(() =>
    {
          string fileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt";
          return UploadFileToSFTP(fileName, fileContent);
    });
}

以下是否适用于我,为我提供不同的日期时间文件名,或者有更好的方法吗?

processingTasks = 1000;
while (processingTasks > 0)
{
     processingTasks --;
     Task<string> task = Task<string>.Factory.StartNew(() =>
     {
           lock(file) //Will only one task go inside this at a time?
           {
               Thread.Sleep(1000);
               string fileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt";
           }

           return UploadFileToSFTP(fileName, fileContent);
     });
}

3 个答案:

答案 0 :(得分:1)

如果两个任务在同一秒内执行,那么文件名将不是唯一的。 解决方案是拥有一个全局(可能是静态的)数字生成器。

public static class NumberGenerator
{
    static object syncObject = new Object();
    static int nextNr = 0;
    public static int NextNumber
    {
        get
        { 
            lock (syncObject)
            {
                nextNr++;
                return nextNr;
            }
        }
    }
}

string filename = NumberGenerator.NextNumber + ".txt";

答案 1 :(得分:1)

您可以使用Emile的想法生成“唯一时间戳”:如果此时间尚未返回,则返回DateTime.Now,否则将来第一次免费返回。

这样,你会得到一个不正确的时间戳(如果你长时间每秒多次调用这个方法,那么你会得到一个很大的数量),但这意味着你不必等待,这让我觉得很脆弱。

在代码中:

public static class UniqueTimestamp
{
    private static readonly object Lock = new object();
    private static DateTime LastTimestamp = DateTime.MinValue;

    private static DateTime RoundToSecond(DateTime dt)
    {
        return new DateTime(dt.Year, dt.Month, dt.Day,
                            dt.Hour, dt.Minute, dt.Second);
    }

    public static DateTime GetTimestamp()
    {
        var now = RoundToSecond(DateTime.Now);
        DateTime timestamp;
        lock (Lock)
        {
            if (now > LastTimestamp)
                timestamp = now;
            else
                timestamp = LastTimestamp.AddSeconds(1);
            LastTimestamp = timestamp;
        }
        return timestamp;
    }
}

答案 2 :(得分:0)

您可以将Task.CurrentId属性合并到您的文件名中。