3 回答

TA貢獻1854條經(jīng)驗 獲得超8個贊
我將通過首先取消之前的操作來開始寫入文件。我還將在延遲任務(wù)中包含取消標(biāo)記。
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);
}

TA貢獻1946條經(jīng)驗 獲得超4個贊
你的背景對我來說似乎有點奇怪。您正在寫入所有字節(jié),而不是使用流。撇開取消令牌的問題不談,將寫入延遲 1 秒不會減少磁盤的總體負(fù)載或總體吞吐量。
這個答案有以下假設(shè):
您正在使用 SSD 并且擔(dān)心硬件壽命
這是一個低優(yōu)先級的活動,可以容忍一些數(shù)據(jù)丟失
這不是日志記錄活動(否則附加到文件會更好地使用 a
BufferedStream
)這可能是將序列化的 C# 對象樹保存到磁盤以防斷電
您不希望對對象樹所做的每個更改都會導(dǎo)致寫入磁盤。
如果對象樹沒有變化,您不想每秒都寫入磁盤。
如果 N 秒內(nèi)沒有寫入,它應(yīng)該立即寫入磁盤
如果最近有寫入,它應(yīng)該等待。
將 WriteAllBytes 步驟作為節(jié)流點并不理想。
用法:
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);
}
}

TA貢獻1820條經(jīng)驗 獲得超10個贊
您應(yīng)該使用 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();
}
}
- 3 回答
- 0 關(guān)注
- 91 瀏覽
添加回答
舉報