用于演示线程的基本C#应用程序无法正常工作 [英] Basic C# App to Demo Threading Not working

查看:93
本文介绍了用于演示线程的基本C#应用程序无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个基本应用,以读取文件同步和异步.异步工作正常,但同步却不行.当我在syncRead()中放置一个断点时,我收到以下消息:System.Windows.Forms.dll中发生了类型为"System.Threading.ThreadStateException"的未处理的异常.
附加信息:在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式.确保您的Main函数上已标记STAThreadAttribute.仅当将调试器附加到进程时,才会引发此异常."
我已经设置了[STAThread]属性.我确定这是显而易见的东西!?!?

代码如下:

I''m writing a basic app to read a file sync and async. Async works fine but sync does not. When I put a breakpoint in syncRead() I get the following message:"An unhandled exception of type ''System.Threading.ThreadStateException'' occurred in System.Windows.Forms.dll

Additional information: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process."
I have set the [STAThread] attribute. I''m sure it''s something blindingly obvious!?!?

Here''s the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Threading;

namespace Streams
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]

        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace Streams
{
    public partial class Form1 : Form
    {
        FileStream fs;
        byte[] fileContents;
        AsyncCallback callback;

        public void syncRead()
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.ShowDialog();
            FileStream fs;
            try
            {
                fs = new FileStream(ofd.FileName, FileMode.OpenOrCreate);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            fs.Seek(0, SeekOrigin.Begin);
            byte[] fileContents = new byte[fs.Length];
            fs.Read(fileContents, 0, (int)fs.Length);
            tbResults.Text = Encoding.UTF8.GetString(fileContents);
            fs.Close();
        }

        public Form1()
        {
            InitializeComponent();
        }
        private void fs_StateChanged(IAsyncResult asyncResult)
        {
            if (asyncResult.IsCompleted)
            {
                tbResults.Text = Encoding.UTF8.GetString(fileContents);
                fs.Close();
            }
        }
        private void btnReadAsync_Click(object sender, EventArgs e)
        {
            openFileDialog.ShowDialog();
            callback = new AsyncCallback(fs_StateChanged);
            fs = new FileStream(openFileDialog.FileName, FileMode.Open,
            FileAccess.Read, FileShare.Read, 4096, true);
            fileContents = new Byte[fs.Length];
            fs.BeginRead(fileContents, 0, (int)fs.Length, callback, null);
        }

        private void btnReadSync_Click(object sender, EventArgs e)
        {
            Thread thdSyncRead = new Thread(new ThreadStart(syncRead));
            thdSyncRead.Start();
        }
    }
}

推荐答案

与GUI线程之外的其他线程中的GUI元素无法进行交互.如果要执行此操作,则必须更改设计.例如,必须将创建和显示对话框委托给GUI线程. GUI线程是应用程序的默认线程.
假设您有一个带有一些编辑框的表单,并且想要从GUI线程之外的另一个线程更改这些编辑框的文本值,那么您还需要修改代码,因为实际的更改需要在GUI线程上完成.
我现在正在出差,所以我不能给我自己的例子,但这涉及调用invoke和使用委托.如果需要,可以通过在要进行更改的控件上调用invokerequired来检查是否确实需要这样做.我非常确定对话框也需要通过GUI线程通过相同的机制创建.
可以在这里找到示例:
http://msdn.microsoft.com/en-us/library/ms171728 (v = vs.80).aspx [
It is not possible to interact with GUI elements from different threads than the GUI thread. If you want to do this, you have to change your design. For instance creating and showing dialogs must be delegated to the GUI thread. The GUI thread being the default thread of your application.
Suppose you have a form with some edit boxes and you want to change these edit boxes text values from another thread than the GUI thread, then you need to modify your code as well, because the actual change needs to be done on the GUI thread.
I am on a business trip right now so I cannot give you an example of my own, but this involves calling invoke and using a delegate. If needed you can check if this is really needed by calling invokerequired on the control on which you want to do the change. I am quite sure for dialogs that they need to be created from the GUI thread too via the same mechanism.
An example can be found here :
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx[^]


这篇关于用于演示线程的基本C#应用程序无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆