Reputation: 23
I have IHostedService
inheritor service, with process some data, and store the last part in a variable.
public class MyService : IHostedService
{
private DataType lastData;
public DataType GetLastData()
{
return lastData;
}
public void ProcessNextPart()
{
...
}
}
I also have api controller, which use DI to call MyService
.
Should i use lock
or some other approach for lastData
in this case? As I understand, simultaneous reading (from controller) and writing (from service) for that variable is possible?
Thanks.
Upvotes: 0
Views: 880
Reputation: 39027
It all depends on whether DataType
is a class or a struct.
If it's a class, then writing it is atomic, so it's pretty much safe. If you think the caller could use that value in a loop, then you may want to add a volatile read to prevent the value from being cached in a register:
public class MyService : IHostedService
{
private DataType lastData;
public DataType GetLastData()
{
return Volatile.Read(ref lastData);
}
public void ProcessNextPart()
{
lastData = newValue;
}
}
But given the use-case, that sounds highly unlikely.
If DataType
is a struct, then it's a whole different story. If the struct is bigger than the target architecture pointer size (4 bytes for x86, 8 bytes for x64), then writing it isn't atomic. Even if the struct is small enough, I don't recommend relying on it since you could add more fields later and break this code. So you have two solutions: either use a lock, or box the value.
Using a lock:
public class MyService : IHostedService
{
private readonly object syncRoot = new object();
private DataType lastData;
public DataType GetLastData()
{
lock (syncRoot)
return lastData;
}
public void ProcessNextPart()
{
lock (syncRoot)
lastData = newValue;
}
}
Boxing the value:
using System.Runtime.CompilerServices;
public class MyService : IHostedService
{
private readonly object syncRoot = new object();
private StrongBox<DataType> lastData;
public DataType GetLastData()
{
return lastData.Value;
}
public void ProcessNextPart()
{
lastData = new StrongBox<DataType>(newValue);
}
}
Upvotes: 1