none
OpenFileDialog函数放在方法里,在xp系统下可行,在win7中怎么不行呢?急 RRS feed

  • 问题

  • OpenFileDialog函数放在方法里,在xp系统下可行,在win7中怎么不行呢?


    下面窗口程序只有一个按钮

    ----------------------
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                CheckForIllegalCrossThreadCalls = false;
            }
            private void button1_Click(object sender, EventArgs e)
            {
                Thread thb = new Thread(bsd);
                thb.Start();

            }
            private void bsd()
            {
                OpenFileDialog opd1 = new OpenFileDialog();
                if (opd1.ShowDialog().ToString() == "OK")
                {
                    MessageBox.Show("aaa");
                }
            }
        }
    }

    2011年9月24日 5:01

答案

  • 这种方式很危险的。CheckIllegalCrossThreadCalls = false 表示 CLR 不检查任何非法的线程拥有性,也就是不论线程中的代码是否被该线程拥有,代码都会被执行。这种明显的安全问题最好是把它挡在门外。

    OpenFileDialog 属于 UI 线程上的东西,在另一个线程中本来是打不开的,并且您用另外的线程打开 OpenFileDialog 没有什么意义,要修复这段代码,首先把 CheckIllegalCrossThreadCalls 那一行干掉,然后把 bsd 方法改一下:

    public void Bsd() {
        this.Invoke(() => {
            OpenFileDialog dialog = new ...
            ...
        });
    }

    这样,创建 OpenFileDialog 的代码就会在 UI 线程上执行,程序就可以正常工作。

    另外,XP 上可以运行不代表以后系统,如 Windows 7 上可以运行,请尽量采用推荐的、标准的方式来访问系统资源。


    Mark Zhou
    2011年9月26日 10:09

全部回复

  • 你好

    要把你的thread/method 轉成single thread apartment便可

    或者可以嘗試更給你的CODE 成

     

       [STAThread]
            private void bsd()
            {
                System.Threading.Thread.CurrentThread.SetApartmentState(System.Threading.ApartmentState.Unknown);
                OpenFileDialog opd1 = new OpenFileDialog();
                if (opd1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    MessageBox.Show("aaa");
                }
            }
    

     


    看看能不能解決這個問題

    Please correct me if my concept is wrong

     


    Chi
    • 已编辑 ChiYau 2011年9月24日 5:27
    2011年9月24日 5:25
  • Hi 开心果地域,
    欢迎来到MSDN论坛!

    您的问题处理的怎么样了呢?

    如果您还需要任何帮助,不妨告诉我们。

    祝,一切顺利!


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年9月26日 9:35
    版主
  • 这种方式很危险的。CheckIllegalCrossThreadCalls = false 表示 CLR 不检查任何非法的线程拥有性,也就是不论线程中的代码是否被该线程拥有,代码都会被执行。这种明显的安全问题最好是把它挡在门外。

    OpenFileDialog 属于 UI 线程上的东西,在另一个线程中本来是打不开的,并且您用另外的线程打开 OpenFileDialog 没有什么意义,要修复这段代码,首先把 CheckIllegalCrossThreadCalls 那一行干掉,然后把 bsd 方法改一下:

    public void Bsd() {
        this.Invoke(() => {
            OpenFileDialog dialog = new ...
            ...
        });
    }

    这样,创建 OpenFileDialog 的代码就会在 UI 线程上执行,程序就可以正常工作。

    另外,XP 上可以运行不代表以后系统,如 Windows 7 上可以运行,请尽量采用推荐的、标准的方式来访问系统资源。


    Mark Zhou
    2011年9月26日 10:09
  • 在其他线程中访问UI控件时应该用Me.Invoke()方法
    共同努力,共同提高
    kaedei#live.cn My BLOG
    2011年9月27日 3:20
  • dear

    非常不建议使用 CheckForIllegalCrossThreadCalls = false;
    你的问题是跨线程的问题,在子执行绪要更新UI执行绪,必须要用委派+This.Invoke,this.BeginInvoke

    http://www.dotblogs.com.tw/yc421206/archive/2009/02/13/7141.aspx

     

    用MethodInvoker委派可以节省代码

            public void Bsd()
            {
                this.BeginInvoke((MethodInvoker)delegate
                {
                    OpenFileDialog dialog = new OpenFileDialog();
                });
            }

     

    我记得Invoke没有支援Lambda


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2011年9月28日 4:31