为了账号安全,请及时绑定邮箱和手机立即绑定

限制文件操作

限制文件操作

C#
Smart猫小萌 2022-11-21 15:45:04
我有一个字节数组,我想保存在一个文件中。但是,我不想每次更新都写入文件,因为它可以非常频繁地更新。目前我正计划使用类似于以下的方法;class ThrottleTest{    private byte[] _internal_data = new byte[256];    CancellationTokenSource _cancel_saving = new CancellationTokenSource();    public void write_to_file()    {        Task.Delay(1000).ContinueWith((task) =>        {            File.WriteAllBytes("path/to/file.data", _internal_data);        }, _cancel_saving.Token);    }    public void operation_that_update_internal_data()    {        // cancel writing previous update        _cancel_saving.Cancel();        /*         *  operate on _internal_data         */        write_to_file();    }    public void another_operation_that_update_internal_data()    {        // cancel writing previous update        _cancel_saving.Cancel();        /*         *  operate on _internal_data         */        write_to_file();    }}我认为这种方法行不通,因为当我取消令牌一次时,它将永远取消,因此它永远不会写入文件。首先,我想知道我是否在正确的轨道上,上面的代码是否可以工作。如果没有,实现此行为的最佳方法是什么。此外,是否有一种实用的方法可以将其推广到Dictionary<string,byte[]>anybyte[]可以独立修改的地方?
查看完整描述

3 回答

?
哔哔one

TA贡献1854条经验 获得超8个赞

我将通过首先取消之前的操作来开始写入文件。我还将在延迟任务中包含取消标记。


CancellationTokenSource _cancel_saving;


public void write_to_file()

{

    _cancel_saving?.Cancel();

    _cancel_saving = new CancellationTokenSource();

    Task.Delay(1000, _cancel_saving.Token).ContinueWith((task) =>

    {

        File.WriteAllBytes("path/to/file.data", _internal_data);

    }, _cancel_saving.Token);

}


查看完整回答
反对 回复 2022-11-21
?
绝地无双

TA贡献1946条经验 获得超4个赞

你的背景对我来说似乎有点奇怪。您正在写入所有字节,而不是使用流。撇开取消令牌的问题不谈,将写入延迟 1 秒不会减少磁盘的总体负载或总体吞吐量。

这个答案有以下假设:

  • 您正在使用 SSD 并且担心硬件寿命

  • 这是一个低优先级的活动,可以容忍一些数据丢失

  • 这不是日志记录活动(否则附加到文件会更好地使用 a BufferedStream

  • 这可能是将序列化的 C# 对象树保存到磁盘以防断电

  • 您不希望对对象树所做的每个更改都会导致写入磁盘。

  • 如果对象树没有变化,您不想每秒都写入磁盘。

  • 如果 N 秒内没有写入,它应该立即写入磁盘

  • 如果最近有写入,它应该等待。

将 WriteAllBytes 步骤作为节流点并不理想。

用法:

rootObject.subObject.value = 9;
rootObject.Save(token);

支持代码:


TimeSpan minimumDiskInterval = TimeSpan.FromSeconds(60);

DateTime lastSaveAt = DateTime.MinValue;

bool alreadyQueued = false;

public void Save(CancellationToken token)

{

    if (alreadyQueued) //TODO: Interlocked with long instead for atomic memory barrier

        return;

        

    alreadyQueued = true; //TODO: Interlocked with long instead for atomic memory barrier


    var thisSaveAt = DateTime.UtcNow;

    var sinceLastSave = thisSaveAt.Subtract(lastSaveAt);

    var difference = TimeSpan.TotalSeconds - sinceLastSave.TotalSeconds;

    if (difference < 0)

    { 

        

        //It has been a while - no need to delay

        SaveNow();

    }

    else

    {

        //It was done recently

        

    T   Task.Delay(TimeSpan.FromSeconds(difference).ContinueWith((task) =>

        {

            SaveNow();

        }, _cancel_saving.Token);   

    }

}


object fileAccessSync = new object();

public void SaveNow()

{

    alreadyQueued = false; //TODO: Interlocked with long instead for atomic memory barrier

    byte[] serializedBytes = Serialise(this)

    lock (fileAccessSync)

    {

        File.WriteAllBytes("path/to/file.data", serializedBytes);

    }

}


查看完整回答
反对 回复 2022-11-21
?
拉莫斯之舞

TA贡献1820条经验 获得超10个赞

您应该使用 Microsoft 的 Reactive Framework(又名 Rx)- NuGetSystem.Reactive并添加using System.Reactive.Linq;- 然后您可以这样做:


public class ThrottleTest

{

    private byte[] _internal_data = new byte[256];


    private Subject<Unit> _write_to_file = new Subject<Unit>();


    public ThrottleTest()

    {

        _write_to_file

            .Throttle(TimeSpan.FromSeconds(1.0))

            .Subscribe(_ => File.WriteAllBytes("path/to/file.data", _internal_data));

    }


    public void write_to_file()

    {

        _write_to_file.OnNext(Unit.Default);

    }


    public void operation_that_update_internal_data()

    {

        /*

         *  operate on _internal_data

         */


        write_to_file();

    }


    public void another_operation_that_update_internal_data()

    {

        /*

         *  operate on _internal_data

         */


        write_to_file();

    }

}


查看完整回答
反对 回复 2022-11-21
  • 3 回答
  • 0 关注
  • 99 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号