client mfc application,lock用法?
client mfc application,lock用法?
一、Lock定义lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断。它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。这是通过在代码块运行期间为给定对象获取互斥锁来实现的。
在多线程中,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数。这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生。
而在.NET中最好了解一下进程、应用域和线程的概念,因为Lock是针对线程一级的,而在.NET中应用域是否会对Lock起隔离作用,我的猜想是,即不在同一应用域中的线程无法通过Lock来中断;另外也最好能了解一下数据段、代码段、堆、栈等概念。
在C# lock关键字定义如下:
lock(expression) statement_block,其中expression代表你希望跟踪的对象,通常是对象引用。
如果你想保护一个类的实例,一般地,你可以使用this;如果你想保护一个静态变量(如互斥代码段在一个静态方法内部),一般使用类名就可以了。
而statement_block就是互斥段的代码,这段代码在一个时刻内只可能被一个线程执行。
二、简单例子
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Thread thread1 = new Thread(new ThreadStart(ThreadStart1));
thread1.Name = "Thread1";
Thread thread2 = new Thread(new ThreadStart(ThreadStart2));
thread2.Name = "Thread2";
Thread thread3 = new Thread(new ThreadStart(ThreadStart3));
thread3.Name = "Thread3";
thread1.Start();
thread2.Start();
thread3.Start();
Console.ReadKey();
}
static object _object = new object();
static void Done(int millisecondsTimeout)
{
Console.WriteLine(string.Format("{0} -> {1}.Start", DateTime.Now.ToString("HH:mm:ss"), Thread.CurrentThread.Name));
//下边代码段同一时间只能由一个线程在执行
lock (_object)
{
Console.WriteLine(string.Format("{0} -> {1}进入锁定区域.", DateTime.Now.ToString("HH:mm:ss"), Thread.CurrentThread.Name));
Thread.Sleep(millisecondsTimeout);
Console.WriteLine(string.Format("{0} -> {1}退出锁定区域.", DateTime.Now.ToString("HH:mm:ss"), Thread.CurrentThread.Name));
}
}
static void ThreadStart1()
{
Done(5000);
}
static void ThreadStart2()
{
Done(3000);
}
static void ThreadStart2()
{
Done(1000);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
三、简单解释一下执行过程
先来看看执行过程,代码示例如下:
private static object ojb = new object();
lock(obj)
{
//锁定运行的代码段
}
假设线程A先执行,线程B稍微慢一点。线程A执行到lock语句,判断obj是否已申请了互斥锁,判断依据是逐个与已存在的锁进行object.ReferenceEquals比较(此处未加证实),如果不存在,则申请一个新的互斥锁,这时线程A进入lock里面了。
这时假设线程B启动了,而线程A还未执行完lock里面的代码。线程B执行到lock语句,检查到obj已经申请了互斥锁,于是等待;直到线程A执行完毕,释放互斥锁,线程B才能申请新的互斥锁并执行lock里面的代码。
四、Lock的对象选择问题
接下来说一些lock应该锁定什么对象。
1、为什么不能lock值类型
比如lock(1)呢?lock本质上Monitor.Enter,Monitor.Enter会使值类型装箱,每次lock的是装箱后的对象。lock其实是类似编译器的语法糖,因此编译器直接限制住不能lock值类型。退一万步说,就算能编译器允许你lock(1),但是object.ReferenceEquals(1,1)始终返回false(因为每次装箱后都是不同对象),也就是说每次都会判断成未申请互斥锁,这样在同一时间,别的线程照样能够访问里面的代码,达不到同步的效果。同理lock((object)1)也不行。
2、Lock字符串
那么lock(“xxx”)字符串呢?MSDN上的原话是:
锁定字符串尤其危险,因为字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串都只有一个实例,就是这同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。
3、MSDN推荐的Lock对象
通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题。
而且lock(this)只对当前对象有效,如果多个对象之间就达不到同步的效果。
而自定义类推荐用私有的只读静态对象,比如:
private static readonly object obj = new object();
为什么要设置成只读的呢?这时因为如果在lock代码段中改变obj的值,其它线程就畅通无阻了,因为互斥锁的对象变了,object.ReferenceEquals必然返回false。
4、lock(typeof(Class))
与锁定字符串一样,范围太广了。
五、特殊问题:Lock(this)等的详细解释
在以前编程中遇到lock问题总是使用lock(this)一锁了之,出问题后翻看MSDN突然发现下面几行字:通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock (“myLock”) 违反此准则:如果实例可以被公共访问,将出现C# lock this问题。如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。
来看看C# lock this问题:如果有一个类Class1,该类有一个方法用lock(this)来实现互斥:
publicvoidMethod2()
{
lock(this)
{
System.Windows.Forms.MessageBox.Show(“Method2End”);
}
}
如果在同一个Class1的实例中,该Method2能够互斥的执行。但是如果是2个Class1的实例分别来执行Method2,是没有互斥效果的。因为这里的lock,只是对当前的实例对象进行了加锁。
Lock(typeof(MyType))锁定住的对象范围更为广泛,由于一个类的所有实例都只有一个类型对象(该对象是typeof的返回结果),锁定它,就锁定了该对象的所有实例,微软现在建议,不要使用lock(typeof(MyType)),因为锁定类型对象是个很缓慢的过程,并且类中的其他线程、甚至在同一个应用程序域中运行的其他程序都可以访问该类型对象,因此,它们就有可能代替您锁定类型对象,完全阻止您的执行,从而导致你自己的代码的挂起。
锁住一个字符串更为神奇,只要字符串内容相同,就能引起程序挂起。原因是在.NET中,字符串会被暂时存放,如果两个变量的字符串内容相同的话,.NET会把暂存的字符串对象分配给该变量。所以如果有两个地方都在使用lock(“my lock”)的话,它们实际锁住的是同一个对象。到此,微软给出了个lock的建议用法:锁定一个私有的static 成员变量。
.NET在一些集合类中(比如ArrayList,HashTable,Queue,Stack)已经提供了一个供lock使用的对象SyncRoot,用Reflector工具查看了SyncRoot属性的代码,在Array中,该属性只有一句话:return this,这样和lock array的当前实例是一样的。ArrayList中的SyncRoot有所不同
get
{
if(this._syncRoot==null)
{
Interlocked.CompareExchange(refthis._syncRoot,newobject(),null);
}
returnthis._syncRoot;
其中Interlocked类是专门为多个线程共享的变量提供原子操作(如果你想锁定的对象是基本数据类型,那么请使用这个类),CompareExchange方法将当前syncRoot和null做比较,如果相等,就替换成new object(),这样做是为了保证多个线程在使用syncRoot时是线程安全的。集合类中还有一个方法是和同步相关的:Synchronized,该方法返回一个对应的集合类的wrapper类,该类是线程安全的,因为他的大部分方法都用lock来进行了同步处理,比如Add方法:
publicoverridevoidAdd(objectkey,objectvalue)
{
lock(this._table.SyncRoot)
{
this._table.Add(key,value);
}
}
这里要特别注意的是MSDN提到:从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合:
QueuemyCollection=newQueue();
lock(myCollection.SyncRoot){
foreach(ObjectiteminmyCollection){
//Insertyourcodehere.
}
}
最后
注意:应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock (“myLock”) 违反此准则:
1)如果实例可以被公共访问,将出现 lock (this) 问题;
2)如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题;
3)由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题;
最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。
Win7出现microsoft?
microsoft visual c++ runtime library错误解决办法微软官方解释如下:
症状
在 Microsoft Windows XP 中运行自定义 Microsoft Visual C++ 6.0 程序时,您可能会收到以下错误消息:
This application has requested the Runtime to terminate it in an unusual way.Please contact the application''s support team for more information.
原因
如果使用 /GR 和 /MD 编译器开关,并且 Msvcrt.dll 文件和 Msvcirt.dll 文件的版本是 7.0.x,则可能出现此问题。
注意:当使用早于 7.0 版本的 Msvcrt.dll 文件和 Msvcirt.dll 文件时,不会出现此问题。
解决方案
Microsoft 现在提供了一个受支持的修补程序,但该程序只用于解决本文中提到的问题。仅当系统遇到本文描述的特定问题时才可应用此修补程序。此修补程序可能还会接受进一步的测试。因此,如果这个问题没有对您造成严重影响,我们建议您等待包含此修补程序的下一个 Windows XP Service Pack。
要立即解决此问题,请与 Microsoft 产品支持服务联系,以获取此修补程序。
根据微软的方案可以如下解决这个问题:
1、怎么玩早期的 Msvcrt.dll 文件和 Msvcirt.dll 文件。
2、在C:\Program Files\或者是其他软件安装目录下搜索这两个文件。
3、怎么玩微软官方补丁。
有些时候,在你安装、运行某个软件,可能会得到这样一个错误提示:
Microsoft Visual C++ Runtime Library
Runtime Error!
Program:c:/windows/explorer.exe
This application has requested the runtime to terminate it in an unusual way.Please contact the application's support team for more information。 需要说明的是,Microsoft Visual C++ runtime library是微软系统自带的c++运行库,这个错误与IE设置里的脚本调试应该是没什么关系的。
可能的情况是:
一、系统的运行库比较旧,而软件需要的是更新版本的运行库;或者系统里根本就没有软件需要的运行库;
二、系统的运行库损坏的说;
三、软件需要的运行库与系统的语言版本不一致。
一般性处理方法:
零、查毒杀毒,清理系统插件;
一、如果是IE出现这个错误,你应该检查插件了(例如用360),以及尝试打开IE菜单“工具”、“internet选项”,选择“高级”标签,将“启用第三方浏览器扩展(需重启动)”的钩去掉;
二、如果是以前安装的,现在运行出错,建议重新安装;
三、根本无法安装;
3.1、如果提示你丢失诸如“msvcp50.dll、msvcp60.dll、MSVCP60D.DLL、msvci70.dll、msvcp70.dll、msvcp71.dll”,从其他机器或者网上怎么玩后补回到软件目录或者系统system32目录即可;
3.2、软件使用最新版本并且最好是完全版本(别用解锁或者绿色版);
3.3、上微软自动更新打补丁;
打完补丁后还是不行,去微软怎么玩Microsoft Visual C++ 2005 Redistributable Package (x86)
Microsoft Visual C++ 2005 Redistributable Package (x86),安装在未安装 Visual C++ 2005 的计算机上运行使用 Visual C++ 开发的应用程序所需的 Visual C++ 库的运行时组件,此软件包安装 C Runtime (CRT)、Standard C++、ATL、MFC、OpenMP 和 MSDIA 库的运行时组件。对于支持并行部署模式的库(CRT、SCL、ATL、MFC 和 OpenMP),这些运行时组件安装在支持并行程序集的 Windows 操作系统版本的本机程序集缓存中,这一缓存也称为 WinSxS 文件夹。支持的操作系统: Windows 2000 Service Pack 3; Windows 98; Windows 98 Second Edition; Windows ME; Windows Server 2003; Windows XP Service Pack
如何在com文件夹下建立exe文件?
要在计算机的“com”文件夹下建立“.exe”文件,您需要执行以下步骤:
1. 打开命令提示符或 PowerShell。如果您使用的是 Windows 操作系统,可以在开始菜单中找到它,然后右键单击“此电脑”图标,选择“属性”,在弹出的窗口中选择“高级系统设置”选项,然后单击“性能与设置”按钮。在“系统”选项卡中,找到“高级”选项,然后单击“更改”按钮。
2. 在“性能与设置”窗口中,单击“设置”按钮。
3. 在“性能选项”窗口中,找到“文件系统”选项卡,然后单击“更改”按钮。
4. 在“文件系统”选项卡中,选择“C:\Windows\System32”目录。
5. 在“C:\Windows\System32”目录下,找到“C:\Windows\System32\cmd.exe”文件。
6. 右键单击“cmd.exe”文件,选择“以管理员身份运行”。
7. 在命令提示符或 PowerShell 窗口中,输入以下命令:
```
for /r "%comspec%" %%a in (%comspec%) do (
set "exefile=%%a"
set "dir=%%a"
if not defined exefile (
echo!dir! > %comspec%/exefile.log
echo!exefile! > %comspec%/exefile.log
exit /b
)
)
```
这个命令将循环遍历所有的“.com”文件,并将它们保存为“.exe”文件的扩展名。
8. 按下“Enter”键,命令将自动执行,并将所有的“.com”文件保存为“.exe”文件的扩展名。
9. 右键单击这些文件,选择“复制”或“剪切”,然后将它们移动到您的计算机上的“C:\Windows\System32\”目录下。
10. 打开命令提示符或 PowerShell,输入以下命令:
```
start "C:\Windows\System32\cmd.exe" /k
```
11. 您的“.com”文件夹下的“.exe”文件已成功创建。
请注意,这种方法将只对当前用户有效。如果要将“.com”文件夹下的“.exe”文件共享给其他用户,您需要使用 Windows 共享功能。
我登录CF会出现clientmfcapplication该则么办?
首先用360管家系统漏洞,凡是看见出现“.net”、“C++”字样的补丁全打。然后再怎么玩个驱动精灵或者是驱动人生,驱动全部更新到最新。去DirectX官网上更新DirectX 9.0c重启电脑。如果还是不行的话就把关于CF的东西全部删完然后重新装一下CF客户端。
在电脑中运行dxdiag检查DirectX显示状态,若有显示关闭的情况,可以尝试手动更新一次DirectX文件。
尝试更新最新的显卡驱动。
极端情况分析方向,MFC即Microsoft Foundation Classes微软基础类。可以对vc,net等组件进行尝试,总的排查方向是系统问题,而非游戏自身资源问题。
Application已停止工作?
这个错误往往是程序出了比较严重的错误并且系统无法获取错误原因的系统提示。
你不要直接运行程序,在debug模式调试运行,运行到程序崩溃的的地方,会中断,你看一下中断的地方是不是错误所在,如果不是,那么就设断点单步调试找出错误的地方吧。