<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. [设计模式]<<设计模式之禅>>关于迪米特法则

    迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least KnowledgePrinciple,LKP),虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解 ...

  2. 【数论,水题】UVa 11728 - Alternate Task

    题目链接 题意:给出一个数S,求一个最大的数,使这个数所有的因子之和为S; 这个所谓“因子之和”不知道有没有误导性,因为一开始以为得是素数才行.后来复习了下小学数学,比如12的因子分别是1,2,3,4 ...

  3. JavaScript “\”替换成 “\\”

    str=str.replace(/\\/g,'\\\\');

  4. CSS3 变形记

    CSS3 变形 CSS3变形是一些效果的集合,比如平移,旋转,缩放和倾斜效果,每个效果都称为变形函数. transform transform属性向元素应用 2D 或 3D 转换.该属性允许我们对元素 ...

  5. MongoDB - Introduction to MongoDB, Capped Collections

    Overview Capped collections are fixed-size collections that support high-throughput operations that ...

  6. C#保存上传来的图片示例代码

    保存上传图片的方法有很多,在接下来的文章中为大家详细介绍下使用C#是如何做到的,感兴趣的朋友不要错过 复制代码代码如下: [HttpPost]  public string UploadImage() ...

  7. 关于蓝牙设备与ios连接后,自动打开一个app

    How to launch an iphone app when an external accessory is either paired over BT or plugged into dock ...

  8. js解析json读取List中的实体对象示例

    1.由后台action 传给前台是需要将map 转成json格式 复制代码代码如下: Map<String, List> resultMap: JSONObject json = JSON ...

  9. IOS 如何选择delegate、notification、KVO?(转)

    前面分别讲了delegate.notification和KVO的实现原理,以及实际使用步骤,我们心中不禁有个疑问,他们的功能比较类似,那么在实际的编程中,如何选择这些方式呢? 在网上看到一个博客上详细 ...

  10. Amoeba for MySQL MySql集群软件

    一, Amoeba简述    Amoeba for MySQL致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的时候充当query 路由功能,专注 分布式数据库 proxy 开发 ...