posts - 26,  comments - 10,  trackbacks - 0
公告
  2011年10月17日

多线程和异步操作的异同

多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为多线程和异步操作是等同的概念。但是,多线程和异步操作还是有一些区别的。而这些区别造成了使用多线程和异步操作的时机的区别。

异步操作的本质

所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础。 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直 接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开 始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS 这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。

线程的本质

线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。

异步操作的优缺点

因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些 初入,而且难以调试。

多线程的优缺点

多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。

适用范围

在了解了线程与异步操作各自的优缺点之后,我们可以来探讨一下线程和异步的合理用途。我认为:当需要执行I/O操作时,使用异步操作比使用线程+同步 I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting等跨进程的调用。

而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往 往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处 理大量的并发操作时就不合适了。

多线程和异步操作的异同

多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为多线程和异步操作是等同的概念。但是,多线程和异步操作还是有一些区别的。而这些区别造成了使用多线程和异步操作的时机的区别。

异步操作的本质

所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础。 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直 接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开 始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS 这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。

线程的本质

线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。

异步操作的优缺点

因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些 初入,而且难以调试。

多线程的优缺点

多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。

适用范围

在了解了线程与异步操作各自的优缺点之后,我们可以来探讨一下线程和异步的合理用途。我认为:当需要执行I/O操作时,使用异步操作比使用线程+同步 I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting等跨进程的调用。

而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往 往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处 理大量的并发操作时就不合适了。

posted @ 2011-10-17 11:51 Memory 阅读(40) 评论(0) 编辑
  2011年7月14日

 我觉得先登录后启动应用主程序是一个很经典的问题,基本上如果要写一个应用程序都会用到这个的小环节。我在这个问题上挣扎了大半天才找到解决方案,我的实现方法我觉得有点不正宗,如果有哪位高手知道更好的方法欢迎留言指导!!

首先来说一下传统C#WinForm中的实现方法,基本上是在Main函数中根据第一个启动窗口的DialogResult来判断是否实例第二个窗口,DialogResult是在第一个窗口中根据登录情况来设置的。代码如下

主函数代码:

static class Program

{

    [STAThread]

    static void Main()

    {

        try

        {

            Application.EnableVisualStyles();

            Application.SetCompatibleTextRenderingDefault(false);

            frmLogin frm = new frmLogin(); //登录

            if (frm.ShowDialog() == DialogResult.OK)

            {

                Application.Run(new frmMain()); //主窗体

            }

            else

            {

                Application.Exit();

            }

        }

        catch (Exception ex)

        {

            MessageBox.Show(ex.Message, "系统登陆", MessageBoxButtons.OK, MessageBoxIcon.Stop);

            Application.Exit();

        }

    }

}

第一个登录窗口中设置DialogResult的代码:

this.DialogResult = DialogResult.OK;

this.Close();

From: http://www.itc8.cn/a/bianchengleyuan/2011/0126/216.html

参考WinFrom中的这个基本想法,在WPF中实现。我重写了OnStartup函数:

protected override void OnStartup(StartupEventArgs e)

        {

            base.OnStartup(e);

 

            Login loginWindow = new Login();

            loginWindow.ShowDialog();

            result = loginWindow.DialogResult;

            username = loginWindow.UserName;

            if (true == result)

            {

                MainWindow main = new MainWindow(username);

                main.ShowDialog();

            }

          

        } //这里需要注意的一点就是上面要用ShowDialog(),而不能直接调用Show(),Show()是不会返回任何结果的,只有用ShowDialog()才能渠道DialogResult

 

死活都是只能启动第一个窗口登录,然后第二个窗口无法呈现出来。调试后发现main窗口已经实例化了但是ShowDialog()貌似完全不起作用。纠结了。。

这个问题的可能原因有:

1.       MainWindow也就是我要创建的第二个主窗口没有实例化成功;

2.       DialogResult错误导致没有进入MainWindow的实例和显示过程;

3.       第一个窗口在作祟。

经过调试排除第一、二中可能,那么肯定就是第一个窗口设置不对或者哪里出问题了。Google了一下别人WPF的方法,发现有一篇文章中提到了需要将WPFShutDownMode设置为OnExplicitShutdown才行,试了一下,果然生效了!只需要很简单的在Main主函数修改ApplicationShutdownMode,修改代码如下

public static void Main()

        {

            PFM.GUI.App.App app = new PFM.GUI.App.App();

            app.ShutdownMode = ShutdownMode.OnExplicitShutdown;

            app.Run();

        }

让我们来看看这个ShutdownMode是何方神圣。ShutdownMode可以设置为一个ShutdownMode 枚举值,包括三种:OnLastWindowCloseOnMainWindowCloseOnExplicitShutdown,默认值是OnLastWindowClose如果将 ShutdownMode 设置为 OnLastWindowClose,则 Windows Presentation Foundation (WPF) 会在应用程序中的最后一个窗口关闭时隐式调用 Shutdown,即使任何当前已经实例化的窗口被设置为主窗口也是如此(MSDN: http://goo.gl/fAyrD  )最后一句是关键:即使任何当前已经实例化的窗口被设置为主窗口也是如此。因为WPF中默认将在Application中实例化的第一个 Window 对象的引用自动设置为MainWindow

也就是说当我们实例化第一个窗口的时候,它被认为是一个MainWindow,所以当它被关闭的时侯WPF就已经隐式调用了ShutDown所以之后我们在怎么实例化窗口都是徒劳。这就是为什么把ShutdownMode设为显示关闭这样就可以避免上面的问题了。需要注意的是在OnStartUp中记得调用App.Shutdown()来关闭Application

posted @ 2011-07-14 12:21 Memory 阅读(221) 评论(0) 编辑
  2011年6月23日
摘要: . delegate 委托可以理解为cxx 语言中的函数指针,标示了方法调用的回调函数的规范。强类型,便于编译时检查是它的最大优点,从此可以和void * 说再见了。2. event 事件用以delegate委托声明事件,标示响应该事件的回调函数必须符合其声明委托的定义3. lambda 表达式在.net世界中表现为匿名委托,之前又要提到匿名方法(函数)01publicclassTest{02publicvoiddelegateClose();//声明一个无参无返回值的委托03publiceventClose CloseEvent;//声明一个Close对应事件04}05staticvoidM阅读全文
posted @ 2011-06-23 14:43 Memory 阅读(42) 评论(0) 编辑
  2011年6月22日
1.资源类别
asp.net中的资源的存储形式有:
(1).txt :它以嵌入资源(BuildAction:Embed Resource)的形式添加到Assembly,只支持字符串类型。
  优点:适合保存大量类型单一的数据 ex:新闻的正文
  缺点:容易被修改,读取数据麻烦
  操作数据:
  System.IO.Stream str = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("ResourceDemo.language.txt");
(2).resx :以嵌入资源的形式添加到Assembly中,支持多种类型;字符串,图像,声音.....
  操作:
  通过ResXResourceReader类读取
  ex:  ResXResourceReader reader = new ResXResourceReader(string.Format("{0}/{1}.resx", Server.MapPath("."), Session["culture"].ToString()));
IDictionaryEnumerator dic = reader.GetEnumerator();           
while (dic.MoveNext())
{
Response.Write(dic.Value);
}   
(3).resource: 资源形式添加到Assembly中。通过ResourceManager访问
    按照asp.net中资源的作用域分为:
    (1)全局资源(App_GlobalResources):在整个站点中都能共享的资源
访问方法:
(1)) 全局资源在App_GlobalResources文件夹中,asp.net运行时会为每个资源文件生成一个强类型化的类,这些类在Resources命名空间下。
    资源中的个key转化为类的属性。可以通过Resource.类名.key来访问资源
(2))在页面中也可以直接访问资源:<%$ Resource:资源名,key %>
(3))this.GetGlobalResourceObject("");
    (2)本地资源(App_LocalResources):特定于某个页面或者某个小范围内共享的资源
        本地资源要注意命名:本地资源的名称要与它提供给的目标的文件目录一致 ex:提供给default.aspx的资源文件名应为Default.aspx.resx
        提供给default.aspx的法语资源文件名应为:Default.aspx.fr.resx
        访问方法:
        (1)) 通过编程方式
             this.GetLocalResourceObject("");
        (2)) <%$ Resource:key%>
        (3)) 通过隐式声明语法访问:该方法只针对服务端控件,客户端通过添加runat=server来使用该语法规则
             ex:<asp:Button id="Btn" runat="server" meta:resourceKey="Btn"/>
             资源文件中:key:value--->Btn.Text:"确定"
             meta:resourceKey将本地资源中的资源和控件进行绑定-->隐式声名性绑定语法
             使用该语法时应确保 绑定到的控件具有资源文件中指定的属性(字符串应具有与 meta:resourcekey 属性定义的目标和属性的名称相匹配的名称)
             在运行时 .net运行时会自动把在资源文件中指定的属性添加到相应的控件上 
             ex:资源文件中:btn.ForeColor="red" 会将id为btn的控件的ForeColor设置为Red颜色            
             全局资源不能使用隐式声名性语法
全局资源文件
    在 App_GlobalResources文件夾中的文件,即是全局资源文件。App_GlobalResources 文件夹中的任何 .resx 文件都具有全局范围。
    在右鍵方案->加入ASP.NET文件夾 中可以加入App_GlobalResources文件夾
    可以用HttpContext.GetGlobalResourceObject方法讀取全局资源文件
本地资源文件
    本地资源文件是只应用于一个 ASP.NET 页的文件(带有 .aspx、.ascx、.master 等扩展名的 ASP.NET 页)。
    App_LocalResources 文件夹中文件為本地資源文件。
    App_LocalResources 文件夹可以存在于应用程序的任何文件夹中,这与 App_GlobalResources 根文件夹不同。
    通过资源文件名将一组资源文件与特定的网页相关联。
    HttpContext.GetLocalResourceObject方法讀取本地资源文件 
posted @ 2011-06-22 17:29 Memory 阅读(203) 评论(0) 编辑
  2011年4月21日
摘要: 文章出处:http://topic.csdn.net/u/20080627/14/8a91b33a-f35c-4303-85b5-e0a8da462202.html1 多行匹配2 不以某某开头 ,比如不以www开头3 不区分大小写4 2个单元的或操作,比如 www ¦ 3w 都可以这种火龙果回答:1:多行匹配在默认的情况下 . 是不能匹配行结束符的(行结束符有 6 个,具体的可以看看 Pattern 的 API DOC)同样,可以像不匹配大小写匹配那样使用编译参数:Pattern.DOTALL如果还得区分大小写的话,还得加上上面说到的 Pattern.CASE_INSENSITIVE阅读全文
posted @ 2011-04-21 16:27 Memory 阅读(3167) 评论(2) 编辑
  2010年10月21日
摘要: 产品为了适用于西亚的客户,需要支持阿拉伯语言以及调整界面布局以满足阿拉伯国家用户的使用习惯. 阿拉伯国家的使用习惯完全跟我们不一样,他们的界面都是从右到左布局的。 比如:一般我们的网站在左边有个导航栏,习惯从左到右操作。它们的导航栏却在右边,习惯从右到左操作. 经过研究得到以下结论: 1. 在silverlight中支持阿拉伯布局是可行的。   方法:设置控件的FlowDirection属...阅读全文
posted @ 2010-10-21 10:48 Memory 阅读(32) 评论(0) 编辑
  2010年7月7日
摘要: 今天遇到一个问题:需要在点击红色框中的滚动条时,将窗体在最上层显示,点击datagrid的其它地方都能让窗口最上层显示,唯独滚动条不可以。但是在silverlight不能获取到DataGrid的滚动条对象,这点很郁闷。按理说它是DataGrid的一部分,在DataGrid的控件范围内点击都能触发DataGrid的鼠标点击事件,事实却让我很失望。最后找到以下解决方法:1.在DataGrid中查找滚动...阅读全文
posted @ 2010-07-07 18:50 Memory 阅读(697) 评论(3) 编辑
  2010年5月17日
摘要: 所谓的开放API(OpenAPI)是服务型网站常见的一种应用,网站的服务商将自己的网站服务封装成一系列API(Application Programming Interface,应用编程接口)开放出去,供第三方开发者使用,这种行为就叫做开放网站的API,所开放的API就被称作OpenAPI(开放API)。网站提供开放平台的API后,可以吸引一些第三方的开发人员在该平台上开发商业应用,平台提供商可以...阅读全文
posted @ 2010-05-17 20:04 Memory 阅读(34) 评论(0) 编辑
摘要: 见识propertymetadata假如你尝试过自己定义一个dependencyproperty,你一定会发现在dependencyproperty.regist方法中可以传入一个propertymetadata类型的对象,这就是属性的"metadata"。假如你对.net框架比较了解,你对"metadata"这个词应该不生疏,简单地说,metadata就是一个用来描述对象自身的对象,同理,这里的...阅读全文
posted @ 2010-05-17 19:20 Memory 阅读(289) 评论(0) 编辑
  2010年5月5日
摘要: 今天使用Nhibernate遇到一个很诡异的问题: Nhibernate将表中的数据取出后,然后用sql将表清空,接着将刚才取出来的对象save到表中(对对象做了一些修改)。 结果总是存在第一条数据被后面的数据给覆盖了,即使我手动将ID设置为0还是不正确 郁闷中.... 找了一些资料,还是没解决。经过分析确定原因出在了自动增长的ID属性上了(因为新增加的对象能正常保存起,旧对象保存保存不起) ,由...阅读全文
posted @ 2010-05-05 16:06 Memory 阅读(41) 评论(0) 编辑
仅列出标题  下一页