我想编写与此java代码类似的c#代码:
=SUMPRODUCT((Table2[Employee Name]=”James Smith”)*(Table2[Task Month Year]")=”March 2017”/(COUNTIF(Table2[Employee Assigned Date],Table2[Employee Assigned Date]&"")))
答案 0 :(得分:6)
我同意克里斯,Interlocked.Exchange(ref Int32, Int32)
,仅使用0,1是替代。
方法说明:
将32位有符号整数设置为指定值,并返回原始值作为原子操作。
以原子方式设置为给定值并返回先前的值。
可悲的是,Interlocked.Exchange()
没有bool
(并注意Interlocked.Exchange<T>()
是参考类型!)
问题中给出的代码:
public class Syncer
{
private int flag = 0;
// Data is synced periodically and on user request
// and these two calls may overlap
public void SyncData()
{
if (Interlocked.Exchange(ref flag, 1) == 1)
{
return;
}
// Sync data...
// It is enough that one thread is syncing data
Interlocked.Exchange(ref flag, 0);
}
}
答案 1 :(得分:2)
Interlocked.Exchange
正是您要找的。不幸的是,如上所述,你不能将它与bool
一起使用,这是一种耻辱。另一种方法是使用this answer中指出的int
重载。
这个解决方案的“神奇数字”一直让我个人感到困扰。但是有一种方法可以创建一个引用类型,否则就像bool
:
public sealed class RefBool
{
public static implicit operator bool( RefBool value )
{
return value != null;
}
public static implicit operator RefBool( bool value )
{
return value ? RefBool.True : RefBool.False;
}
public static bool operator true( RefBool value )
{
return value != null;
}
public static bool operator false( RefBool value )
{
return value == null;
}
public static readonly RefBool True = new RefBool();
public static readonly RefBool False = null;
private RefBool()
{
}
}
现在你的课程看起来像这样:
public class Syncer
{
private RefBool mIsSyncInProgress = false;
public void SyncData()
{
if (Interlocked.Exchange(ref mIsSyncInProgress, true))
{
return;
}
// Sync data...
// It is enough that one thread is syncing data
Interlocked.Exchange(ref mIsSyncInProgress, false);
}
}
我发现在使用网站上更容易阅读。我发现这个解决方案并不完美,因为RefBool
类有点奇怪。
您应该注意到我使用null
作为错误状态。这是为了确保RefBool
类型的变量只能是true
或false
。如果我使用两个不同的实例来表示true
和false
,那么RefBool
也可能是null
,这将是一个不确定的状态。
这样做的缺点是ToString
无法正常工作(这就是为什么我没有打扰它的原因)。
答案 2 :(得分:1)
我建议您使用Montior.TryEnter(Object, Boolean)
,这最适合您的问题/示例。
但使用Monitor.TryEnter(Object)
可以更好/更紧凑地编写(我会在第一个代码示例下面留下它作为建议)。
public class Syncer
{
private object lockObject = new object();
// Data is synced periodically and on user request
// and these two calls may overlap
public void SyncData() {
bool syncInProgress = false;
try {
Monitor.TryEnter(lockObject, ref syncInProgress);
if (syncInProgress) {
// The critical section.
// Sync data...
// It is enough that one thread is syncing data
}
else {
// The lock was not acquired.
return;
}
}
finally {
// Ensure that the lock is released.
if (syncInProgress) {
Monitor.Exit(lockObject);
}
}
}
}
清洁示例:
public class Syncer
{
private object lockObject = new object();
// Data is synced periodically and on user request
// and these two calls may overlap
public void SyncData() {
if(Monitor.TryEnter(lockObject)){
try {
// The critical section.
// Sync data...
// It is enough that one thread is syncing data
}
finally {
// Ensure that the lock is released.
Monitor.Exit(lockObject);
}
}
else {
// The lock was not acquired.
return;
}
}
}