<a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流

我的博客园网址:http://www.cnblogs.com/lingzeng/MyPosts.html

有编程基础的道友恐怕对 SaveFileDialog都不陌生,一个保存对话框,所以今天目的不是对SaveFileDialog用法的探讨。

今天我所讲述的是SaveFileDialog的跨线程问题,相信很对人都试过在单击事件按钮下弹出SaveFileDialog进行操作,那么如果在一个事件下调用一个线程,且该线程所调用的方法中有队SaveFileDialog的操作,这个时候会出现什么情况?

下面的代码做出演示:

首先解释,该代码是一个客户端发出一个发送文件请求,服务端收到该请求后弹出一个SaveFileDialog进行路径的保存。

客户端的代码省略,附上服务器代码:

private void button1_Click(object sender, EventArgs e)
        {
             //线程,调用下面的一段程序method1()
        }

//省略代码

method1():

      ...........................................
                else if (revMes[0] == 1)//1代表对方发送来的是文件
                {
                    SaveFileDialog sf = new SaveFileDialog();
                    byte[] revMesToTrue = new byte[length - 2];
                    //自定义规则0-〉图片,1-〉文本文件,2->音频文件,3-〉屏幕截图
                    if (revMes[1] == 0)
                    {
                        sf.Filter = "图片|*.jpg;*.png;*.gif;*.JPG;*.PNG;*.GIF";
                        txtRecord.AppendText("接收到服务器图片文件\r\n");
                    }
                    else if (revMes[1] ==1)
                    {
                        sf.Filter = "文本文件|*.txt";
                        txtRecord.AppendText("接收到服务器文本文件\r\n");
                    }
                    else if (revMes[1] == 2)
                    {
                        sf.Filter = "音频文件|*.mp3;*.wav;*.3gp";
                        txtRecord.AppendText("接收到服务器音频文件\r\n");
                    }
                    else if(revMes[1]==3)//3代表截取屏幕
                    {
                        //将图片放在picturebox上,之后将截图窗口的背景图片设为该图
                         Buffer.BlockCopy(revMes, 2, revMesToTrue, 0, revMesToTrue.Length);
                         MemoryStream memorystream = new MemoryStream(revMesToTrue);

pictureBox1.Image = Image.FromStream(memorystream);//770
                         while (this.Width < 770)
                         {
                             this.Width += 50;
                             Thread.Sleep(500);
                         }
                         截图窗口 jietu = new 截图窗口();

for (int i = 0; i < jietu.Controls.Count; i++)
                         {
                             if (jietu.Controls[i] is PictureBox)
                             {
                                 PictureBox picturebox = jietu.Controls[i] as PictureBox;
                                 picturebox.Image = Image.FromStream(memorystream);
                             }
                         }
                         jietu.Show();
                         Application.Run(jietu);
                          return;
                    }
                    //保存文件对话框
                    if (sf.ShowDialog() == DialogResult.OK)
                    {
                        using (FileStream fs = new FileStream(sf.FileName, FileMode.Create, FileAccess.Write))
                        {
                            // byte[] sendMsg = new byte[1024 * 1024 * 5];
                            Buffer.BlockCopy(revMes, 2, revMesToTrue, 0, revMesToTrue.Length);
                            fs.Write(revMesToTrue, 0, revMesToTrue.Length);
                        }
                        txtRecord.AppendText("将文件保存到了" + sf.FileName + "下面\r\n");
                    }
                    else
                    {
                        txtRecord.AppendText("你放弃了保存文件\r\n");
                    }

        .........................................

注意红色部分为SaveFileDialog的操作,执行该代码后发现即使收到文件请求,SaveFileDialog对话框也并未弹出。

经过调试,以及msdn查看,发现问题在sf.ShowDialog();

这里大家看sf.ShowDialog()的两个相关函数

//
        // 摘要:
        //     用默认的所有者运行通用对话框。
        //
        // 返回结果:
        //     如果用户在对话框中单击“确定”,则为 System.Windows.Forms.DialogResult.OK;否则为 System.Windows.Forms.DialogResult.Cancel。
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        public DialogResult ShowDialog();
        //
        // 摘要:
        //     运行具有指定所有者的通用对话框。
        //
        // 参数:
        //   owner:
        //     任何实现 System.Windows.Forms.IWin32Window(表示将拥有模式对话框的顶级窗口)的对象。
        //
        // 返回结果:
        //     如果用户在对话框中单击“确定”,则为 System.Windows.Forms.DialogResult.OK;否则为 System.Windows.Forms.DialogResult.Cancel。
        public DialogResult ShowDialog(IWin32Window owner);
    }

不带参数的sf.ShowDialog()表示默认当前所有者运行对话框,而在本程序中所有者为用户自定义的,并非在button_click()所在的ui界面

所以大家看第二个带参数sf.ShowDialog(IWin32Window owner),运行具有指定所有者的通用对话框。

这里我们传一个参数 this 即sf.ShowDialog(this),this代表当前的Form()窗体,再次运行即可成功实现。

附:从网上搜的另一个方法(没有验证)

在调用的线程后加上thr.SetApartmentState(ApartmentState.STA)这一句就可以了。这句的意思是在线程启动之前设置线程的单元状态为STA,MSDN中将这种问题定义为“STA 线程失去线程令牌”,它将导致作为一个的结果来打开文件、数据库,和等上的安全调用可能会失败。

<a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------

<a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>

黑马程序员 SaveFileDialog的跨线程调用 (专题三)的更多相关文章

  1. 黑马程序员 c#单态的设计模式 (专题二)

    <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IO开发S</a> ...

  2. 课程10:《黑马程序员_Hibernate开发资料》视频目录--没有细看

    老师很厉害,讲得蛮详细的 \Hibernate视频教程\01_黑马程序员_Hibernate教程__Hibernate入门基础.avi; \Hibernate视频教程\02_黑马程序员_Hiberna ...

  3. 黑马程序员:Java基础总结----网络编程

    黑马程序员:Java基础总结 网络编程   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 网络编程 网络通讯要素 . IP地址 . 网络中设备的标识 . 不易记忆,可用 ...

  4. 黑马程序员:轻松精通Java学习路线连载1-基础篇!

    编程语言Java,已经21岁了.从1995年诞生以来,就一直活跃于企业中,名企应用天猫,百度,知乎......都是Java语言编写,就连现在使用广泛的XMind也是Java编写的.Java应用的广泛已 ...

  5. 【黑马18期Java毕业生】黑马程序员Java全套资料+视频+工具

        Java学习路线图引言:        黑马程序员:深知广大爱好Java的人学习是多么困难,没视频没资源,上网花钱还老被骗. 为此我们历时一个月整理这套Java学习路线图,不管你是不懂电脑的小 ...

  6. 黑马程序员——【Java高新技术】——代理

    ---------- android培训.java培训.期待与您交流! ---------- 一.“代理概述”及“AOP概念” (一)代理概述 1.问题:要为已存在的多个具有相同接口的目标类的各个方法 ...

  7. C# 跨线程调用控件

    在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应.  同时我们又需要在工作线程中更新UI界面上的控件, 下面介绍几种常用的方法 阅读目录 线程间操作无效 第一种办法:禁 ...

  8. 黑马程序员_ JAVA中的多线程

    ------- android培训.java培训.期待与您交流! ---------- 尽管线程对象的常用方法可以通过API文档来了解,但是有很多方法仅仅从API说明是无法详细了解的. 本来打算用一节 ...

  9. 黑马程序员—C语言的函数、数组、字符串

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.函数 定义:函数是代码复用的一种机制. 函数的基本语法: 返回类型 函数名 ( 参数类型 参 ...

随机推荐

  1. [改善Java代码]若有必要,使用变长数组

    Java中的数组是定长的,一旦经过初始化声明就不可改变长度,这在实际使用的时候非常不方便.比如要对一个班级的学生信息进行统计,因为我们不知道班级会有多少个学生(随时可能有退学,入学,转学),所以需要一 ...

  2. C#控制台程序 使用 Server.MapPath,

    (1)添加引用 System.Web. (2)在类中填写 using System.Web 命名空间. (3)写法为: System.Web.HttpContext.Current.Server.Ma ...

  3. Html5中的video元素

    最近在做门户的时候遇到要显示企业的视频介绍,需要找到一个在aspx页面播放视频的html,最后找到了是一段HTML5最新的html代码,如下: /// <summary> /// 播放视频 ...

  4. 如何更好的理解(pageX,pageY,clientX,clientY,eventX,eventY,scrollX,scrollY,screenX,screenY,event.offsetX,event.offsetY,offsetLeft,style.left)

    1 pageX,pageY:鼠标指针相对于当前窗口的X,Y坐标,计算区域包括窗口自身的控件和滚动条.(火狐特有) 2 event.clientX,event.clientY:鼠标指针相对于当前窗口的X ...

  5. MySQL之经典语句

    数据库的创建:(例如创建名为ConstructionDB的数据库) --创建SelfStudy数据库 CREATE DATABASE ConstructionDB ON PRIMARY --创建主数据 ...

  6. oracle安装分析

    oracle的安装 1.下载Oracle 11g 2.解压两个压缩包到同一目录(内容合并),即"database",然后单击解压目录下的"setup.exe"文 ...

  7. 读<<CLR via C#>> 详谈泛型

    1,什么是泛型? 答:泛型是类型的模板,类型是实例(对象)的模板.C#提供了5种泛型:类,接口,委托,结构和方法. 2,使用泛型有什么好处? 答:继承实现的是"代码重用",而泛型实 ...

  8. (转)使用Amoeba 实现MySQL DB 读写分离

    Amoeba(变形虫)项目是一个开源框架,于2008年开始发布一款 Amoeba for Mysql软件: 这个软件致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的时候充当SQ ...

  9. 移动web屏幕适配方案

    刚进部门就被拉去趟移动端Web的浑水,视觉稿是按照640px设计的.那如何做屏幕适配呢?当然想到的第一方法就是问前辈了,问他们之前怎么做的,前辈说直接按视觉稿来,我说640太大了,他说除以2啊,按32 ...

  10. javascript笔记——placehold

    <input type="text" name="搜索" value="搜索" placeholder="搜索" ...