我有一些问题ReaderWriterLockSlim.我无法理解它是如何运作的.
我的代码:
private async Task LoadIndex()
{
if (!File.Exists(FileName + ".index.txt"))
{
return;
}
_indexLock.EnterWriteLock();// <1>
_index.Clear();
using (TextReader index = File.OpenText(FileName + ".index.txt"))
{
string s;
while (null != (s = await index.ReadLineAsync()))
{
var ss = s.Split(':');
_index.Add(ss[0], Convert.ToInt64(ss[1]));
}
}
_indexLock.ExitWriteLock();<2>
}
Run Code Online (Sandbox Code Playgroud)
当我在输入写锁定<1>,在调试器我可以看到_indexLock.IsWriteLockHeld是true,但是当执行步骤<2>我看_indexLock.IsWriteLockHeld是false
和_indexLock.ExitWriteLock抛出异常SynchronizationLockException处理消息"写锁定而不被保持被释放".我做错了什么?
与计时器一起玩.上下文:带有两个标签的winforms.
我想知道如何System.Timers.Timer工作,所以我没有使用Forms计时器.我知道表单和myTimer现在将在不同的线程中运行.是否有一种简单的方法来表示lblValue以下表格中的经过时间?
我在MSDN上看过这里,但有更简单的方法!
这是winforms代码:
using System.Timers;
namespace Ariport_Parking
{
public partial class AirportParking : Form
{
//instance variables of the form
System.Timers.Timer myTimer;
int ElapsedCounter = 0;
int MaxTime = 5000;
int elapsedTime = 0;
static int tickLength = 100;
public AirportParking()
{
InitializeComponent();
keepingTime();
lblValue.Text = "hello";
}
//method for keeping time
public void keepingTime() {
myTimer = new System.Timers.Timer(tickLength);
myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
myTimer.AutoReset = true;
myTimer.Enabled = true;
myTimer.Start();
}
void …Run Code Online (Sandbox Code Playgroud) 让我们假设我们必须同步对共享资源的读/写访问.多个线程将在读取和写入时访问该资源(大多数时间用于读取,有时用于写入).让我们假设每次写入总是触发读操作(对象是可观察的).
对于这个例子,我会想象一个这样的类(原谅语法和风格,它仅用于说明目的):
class Container {
public ObservableCollection<Operand> Operands;
public ObservableCollection<Result> Results;
}
Run Code Online (Sandbox Code Playgroud)
我很想将a ReadWriterLockSlim用于此目的而且我把它放在Container水平上(想象对象不那么简单,一个读/写操作可能涉及多个对象):
public ReadWriterLockSlim Lock;
Run Code Online (Sandbox Code Playgroud)
的实施Operand和Result对这个例子没有意义.现在让我们想象一些观察Operands并将产生结果的代码Results:
void AddNewOperand(Operand operand) {
try {
_container.Lock.EnterWriteLock();
_container.Operands.Add(operand);
}
finally {
_container.ExitReadLock();
}
}
Run Code Online (Sandbox Code Playgroud)
我们的hypotetical观察者会做类似的事情,但是要使用一个新元素,它将锁定EnterReadLock()以获取操作数然后EnterWriteLock()添加结果(让我省略代码).这会因为递归而产生异常但是如果我设置LockRecursionPolicy.SupportsRecursion那么我只是打开我的代码到死锁(来自MSDN):
默认情况下,使用LockRecursionPolicy.NoRecursion标志创建ReaderWriterLockSlim的新实例,并且不允许递归.建议对所有新开发使用此默认策略,因为递归会引入不必要的复杂性并使您的代码更容易出现死锁.
为清楚起见,我重复相关部分:
递归[...]使您的代码更容易出现死锁.
如果我没有错,LockRecursionPolicy.SupportsRecursion如果来自同一个线程,我问一个,比方说,读取锁定,然后其他人要求写入锁定然后我将有一个死锁然后MSDN说的是有道理的.此外,递归也会以可测量的方式降低性能(如果我使用的话,它不是我想要的,ReadWriterLockSlim而不是ReadWriterLock或者Monitor).
最后我的问题是(请注意我不是在寻找关于通用同步机制的讨论,我知道这个生成器/ observable/observer场景有什么问题):
ReadWriterLockSlim赞成Monitor(即使在现实世界中,代码读取将远远超过写入)? …我有一个名为IDataIO的界面:
public interface IDataIO
{
event DataReceivedEvent DataReceived;
//.....more events,methods and properties
}
Run Code Online (Sandbox Code Playgroud)
我也有一个实现此接口,即多个类UdpIO,TcpIO,SerialIO.
现在,我有一个IO类允许我在不同的输入/输出硬件之间切换.这个类的每个实例都有一个CurrentIODevice属性,它可以是一个SerialIO,UdpIO或TcpIO.分配此属性后,我会附加一个或多个处理程序,DataReceivedEvent以便在收到传入数据时通知我的GUI,以及需要通知的其他类.
public class IO
{
IDataIO CurrentIODevice;
public IO()
{
SerialIO serial = new SerialIO();
TcpIO tcp = new TcpIO();
UdpIO udp = new UdpIO();
CurrentIODevice = serial;
}
}
Run Code Online (Sandbox Code Playgroud)
我还有一个IOManager包含多个IO对象的类.
public class IOManager
{
List<IO> Ports = new List<IO>();
public IOManager()
{
Ports.Add(new …Run Code Online (Sandbox Code Playgroud) 我需要"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{26A24AE4-039D-4CA4-87B4-2F86416024FF}"在c ++中打开一个注册表项.它包含java 64位应用程序.该注册表项的完整路径是"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{26A24AE4-039D-4CA4-87B4-2F86416024FF}".
我们可以通过regedit查看此路径.我用
returnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{26A24AE4-039D-4CA4-87B4-2F86416024FF}"),
0, KEY_ALL_ACCESS, &hKey)
Run Code Online (Sandbox Code Playgroud)
打开注册表; 但它返回错误值(2).
returnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall")...
Run Code Online (Sandbox Code Playgroud)
返回成功结果.我能做什么?
以下代码在Visual Studio 2010中生成警告C4127(条件表达式是常量)(其中alias_wchar_t是wchar_t的别名):
if (sizeof(alias_wchar_t) == sizeof(wchar_t)) // warning occurs here
{
// do stuff
}
else
{
// do other stuff
}
Run Code Online (Sandbox Code Playgroud)
除了抑制警告之外,解决这个问题的最优雅方法是什么?
我想出的最好的解决方案是将条件填充到静态bool中,并将其用作条件.在if-else之上和之下都有大量的代码,所以我将整个东西包装在大括号中以尽可能地限制变量的范围:
// <snip>
{
static bool isSameSize = (sizeof(alias_wchar_t) == sizeof(wchar_t));
if (isSameSize)
{
// do stuff
}
else
{
// do other stuff
}
}
// <snip>
Run Code Online (Sandbox Code Playgroud)
这感觉非常糟糕.这似乎应该在编译时而不是运行时可解析,但预处理器不知道sizeof.是否有更清洁,更优雅的方法来解决这个问题?
想象一下,我有下面的代码.我怎样才能通过反思得到MemberInfo/PropertyInfo"明确"的实施Test.Name?
另外,有没有办法以编程方式知道a MemberInfo是接口属性的显式实现?
public interface ITest
{
string Title { get; set; }
}
public interface IExplicit
{
string Name { get; set; }
}
public class Test : ITest,IExplicit
{
public string Title { get; set; }
string IExplict.Name
{
get
{
return this.Title;
}
set
{
}
}
}
Run Code Online (Sandbox Code Playgroud) 我有这个方法:
public static void testConnection()
{
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
System.Windows.MessageBox.Show("This computer is connected to the internet");
}
else
{
System.Windows.MessageBox.Show("This computer is not connected to the internet");
}
}
Run Code Online (Sandbox Code Playgroud)
我想它会告诉我连接是否可用但它总是返回true(并打印第一条消息),即使我确定没有连接.我做错了什么?
PS:我还在学习C#.
回答这个问题让我觉得有些事情对我来说还不清楚.我们首先假设我们从这篇文章和这篇文章中读到了所有内容.
[开始编辑]也许它不是那么明显(意大利幽默?!)但标题只是非常具有挑衅性:当然应该有一个原因,如果volatile已经包含在C#中,我只是无法理解确切的一个.[结束编辑]
总之,我们知道我们有三个工具来共享线程之间的变量:
lock 因为这会阻止指令重新排序.volatile因为将强制CPU始终从内存中读取值(然后不同的CPU /内核不会缓存它,并且它们将看不到旧值).Increment/ Decrement和CompareExchange)因为它们将在单个原子(我不明白(C#规格参考将不胜感激):
Interlocked.CompareExchange()与朋友一起实施,他们与众不同?volatile例如,在此代码中,修饰符将执行什么操作?
volatile int _volatileField = 0;
int _normalField = 0;
void test()
{
Interlocked.Increment(ref _normalField);
++_volatileField;
}
Run Code Online (Sandbox Code Playgroud)
[开始编辑]前面的例子涉及原子读取+写入,让我们改变它_volatileField = 1;,在这里我不是在谈论原子操作.[结束编辑]
此外,什么编译器(旁边的警告)将在这里做:
Interlocked.Increment(ref _volatileField);
Run Code Online (Sandbox Code Playgroud)
它们似乎是完全不同的东西(正如我想象的那样)但是对于我的理解Interlocked.Increment()操作数应该隐含地是易变的(然后它将仅添加原子增量).非易失性领域怎么可能?他们也暗示了障碍吗?这不会影响性能(与易失性相比)吗?
如果volatile不暗示障碍但其他人不这样做那么为什么我们不能将它们用作局部变量?特别是当在例如并行循环中使用时,这将以显着的方式损害性能(我正在考虑具有很少代码的小函数,这些代码适用于可以很好地使用数据高速缓存的大量数据).
[开始编辑]我发现以前的句子真的不清楚(抱歉我的英文).我的意思是:如果性能(的volatile …
我刚看到这个问题:在C#中对File类使用静态方法是否安全?.总结一下IOException,在这个ASP.NET代码片段中,OP有一个因为文件正在使用:
var text= File.ReadAllText("path-to-file.txt");
// Do something with text
File.WriteAllText("path-to-file.txt");
Run Code Online (Sandbox Code Playgroud)
我的第一个想法是,由于多个ASP.NET重叠请求,这是一个简单的并发访问问题.我要解决的问题是将I/O集中到同步的线程安全类中(或者删除文件以支持其他内容).我读了两个答案,当我即将向其中一个人投票时,我看到那些用户是谁,我想到了什么,并且停止了.
我会引用它们两者(然后请参阅原始答案以获取更多背景信息).
对于这个OP段:
我猜测文件读取操作有时不会在写操作发生之前关闭文件[...]
答案说:
正确.文件系统不支持原子更新[...]使用FileStream没有帮助[...]文件里面没有魔法.它只是为了您的方便而使用FileStream包装.
但是我没有看到任何期望的原子操作(读取+后续写入)和并行(因为部分重叠的多线程请求)可能导致并发访问.即使是原子 I/O操作(读/写)也会有完全相同的问题.OK FileStream 可以是异步的,但它不是如何File.ReadAllText()和File.WriteAllText()使用它.
另一个答案使我更加困惑,它说:
虽然根据文档,该方法保证文件句柄被关闭,但即使引发异常,也不能保证在方法返回之前发生关闭的时间:关闭可以异步完成.
什么?MSDN说方法将打开,读取和关闭文件(如果是异常).这种方法是否有可能异步关闭文件?OS会推迟CloseHandle()吗?在哪些情况下?为什么?
简而言之:它只是一种误解还是CloseHandle()异步?我错过了一些非常重要的东西?