Home > Blockchain >  How to create a task that watches the size of a file in a c# console application
How to create a task that watches the size of a file in a c# console application

Time:11-08

I'm working on a C# project that will need to create text files and fill them with guids using an array of 25 tasks. I want to use another task separate from the writing tasks to monitor the size of the file at 0.5 second intervals.

I'm struggling to figure out a way to do this. I know with a C# WPF application I could use the FILEIO class but I don't think I have access to that using a console app.

What could I use instead of the FILEIO class to create this task and how would I create it?

CodePudding user response:

you can create a new Thread and use the Length property of a System.IO.FileInfo object to get the size of a file.

See this link for more details on Threading.

CodePudding user response:

How about something like this. Everything is asynchronous. The only thread created monitors the count (so that you can see what's going on - which is the point of this, I think).

First I create a class like this:

internal class GuidWriter
{
    public string Folder { get; }
    public string FileNamePattern { get; }
    public int CountOfFiles { get; }
    public int CountOfGuids { get; }
    public int TotalGuidsToWrite { get; }

    private int _currentGuidCount = 0;
    public int CurrentGuidCount { get { return _currentGuidCount; } }

    public GuidWriter(string folder, string fileNamePattern, int countOfFiles, int countOfGuids)
    {
        Folder = folder;
        FileNamePattern = fileNamePattern;
        CountOfFiles = countOfFiles;
        CountOfGuids = countOfGuids;
        TotalGuidsToWrite = countOfFiles * countOfGuids;
    }

    public async Task WriteAllFiles()
    {
        var writeTaskList = new List<Task>(CountOfFiles);
        for (int i = 0; i < CountOfFiles; i  )
        {
            var writeTask = WriteGuidsToOneFile(i   1);
            writeTaskList.Add(writeTask);
        }
        await Task.WhenAll(writeTaskList);
    }

    private async Task WriteGuidsToOneFile(int fileNumber)
    {
        var fileName = string.Format(FileNamePattern, fileNumber);
        var filePathName = Path.Combine(Folder, fileName);
        using (StreamWriter writer = File.CreateText(filePathName))
        {
            for (var i = 0; i < CountOfGuids;   i)
            {
                var guidString = Guid.NewGuid().ToString();
                await writer.WriteLineAsync(guidString);
                Interlocked.Increment(ref _currentGuidCount);
            }
        }

    }
}

You create one of these things, tell it how it should work (in the constructor) and then let it rip in the WriteAllFiles (which is async, and which you should await).

It uses Interlocked.Increment on the Guid count - if the framework doesn't anything in threads, I want to make sure that I don't mess up the count.

Then in the main program, I create a Monitor function that counts the number of Guids created and outputs them to the console. It runs in a separate thread, and will go away when it's CancellationToken is canceled:

public static async Task MonitorGuidProduction (GuidWriter guidWriter, CancellationToken cancellationToken)
{
    while (!cancellationToken.IsCancellationRequested)
    {
        var monitorString = $"{guidWriter.CurrentGuidCount}/{guidWriter.TotalGuidsToWrite}";
        Console.WriteLine(monitorString);
        await Task.Delay(500);
    }
}

Then, in the main program, I put it all together:

static async Task Main(string[] args)
{
    using (var cancelTokenSource = new CancellationTokenSource())
    {
        var cancelToken = cancelTokenSource.Token;
        var folder = @"C:\temp\guids";
        var pattern = "GuidFile{0}.txt";
        var guidWriter = new GuidWriter(folder, pattern, CountOfFiles, CountOfGuids);
        Task.Run(() => MonitorGuidProduction(guidWriter, cancelToken));
        await guidWriter.WriteAllFiles();
        cancelTokenSource.Cancel();

        Console.WriteLine($"{guidWriter.CurrentGuidCount} Guids written to {CountOfFiles} files");
        Console.ReadLine();
    }
}

I create an instance of a GuidWriter and, just before I let it go (by calling guidWriter.WriteAllFiles, I start up my monitor function in another thread (by calling an un-awaited Task.Run).

Then I await the call to guidWriter.WriteAllFiles, and when it completes, I signal my cancellation token to stop the monitor task/thread.

  •  Tags:  
  • c#
  • Related