gpt4 book ai didi

visual-studio - Visual Studio调试器的线程问题

转载 作者:行者123 更新时间:2023-12-03 12:50:59 25 4
gpt4 key购买 nike

我有一个旨在通过网络运行的应用程序。这意味着此应用程序的初始运行可能需要一段时间。因此,我一直在整理启动屏幕,以简化一些流程。

它使用线程通过静态方法显示表单。我还是一个线程新手,所以当我遇到错误时,我对什么以及为什么感到困惑。

当我在Visual Studio调试器之外运行代码时,结果证明我的代码是完美的。但是,当我从调试器内部运行它时,出现了异常:

“跨线程操作无效:无法从创建该线程的线程访问其他线程的控件”。

这是我的课:

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.Threading;

namespace MyApp
{
public partial class SplashScreen : Form
{
private static double OPACITY_INCREMENT = .05;

private static SplashScreen _splashForm;
private static SplashScreen SplashForm
{
get { return SplashScreen._splashForm; }
set { SplashScreen._splashForm = value; }
}

private static void ShowForm()
{
SplashScreen.SplashForm = new SplashScreen();
Application.Run(SplashScreen.SplashForm);
}

internal static void CloseForm()
{
if (SplashScreen.SplashForm != null &&
SplashScreen.SplashForm.IsDisposed == false)
{
// Make it start going away.
OPACITY_INCREMENT = -OPACITY_INCREMENT;
}

SplashScreen.SplashThread = null;
SplashScreen.SplashForm = null;
}

private static Thread _splashThread;
private static Thread SplashThread
{
get { return SplashScreen._splashThread; }
set { SplashScreen._splashThread = value; }
}

internal static void ShowSplashScreen()
{
if (SplashScreen.SplashForm != null)
{
return;
}

SplashScreen.SplashThread = new Thread(new ThreadStart(SplashScreen.ShowForm));
SplashScreen.SplashThread.IsBackground = true;
SplashScreen.SplashThread.SetApartmentState(ApartmentState.STA);
SplashScreen.SplashThread.Start();
}

public SplashScreen()
{
InitializeComponent();
this.timerFade.Start();
this.ClientSize = this.BackgroundImage.Size;
}

private void SplashScreen_Load(object sender, EventArgs e)
{
}

private void timerFade_Tick(object sender, EventArgs e)
{
if (OPACITY_INCREMENT > 0)
{
if (this.Opacity < 1)
this.Opacity += OPACITY_INCREMENT;
}
else
{
if (this.Opacity > 0)
this.Opacity += OPACITY_INCREMENT;
else
{
this.Invoke(new MethodInvoker(this.TryClose));
}
}
}

private void TryClose()
{
if (this.InvokeRequired)
{
this.BeginInvoke(new MethodInvoker(this.TryClose));
}

this.Close();
}
}
}

我从Program.cs Main方法内部调用启动屏幕。
namespace CIMA
{
static class Program
{
// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

SplashScreen.ShowSplashScreen();

// Code omitted for brevity.

SplashScreen.CloseForm();

// Code omitted for brevity.
}
}
}

我希望能够从其他表单之一中调用SplashScreen.CloseForm(),但到目前为止,我还没有尝试过。我对调试器的功能感到困惑。

我想念什么吗?还是如果在调试器中正在运行初始屏幕,我是否必须禁用它?

如果是这样,有什么好的方法呢?如果可能的话,我想避免诉诸于编译符号,因为我讨厌跟踪它们。

最佳答案

在.NET中,不允许您从未创建控件的线程访问控件。在您的代码中,看起来像是一个单独的线程正在创建初始表单,而主线程试图关闭初始表单。

我建议您采取另一种方法:在主线程中创建启动表单,并让单独的线程对其进行更新。

另外,在您的TryClose方法中,我猜是对BeginInvoke的调用之后,缺少返回值。

但是,您可以查看启动屏幕的其他实现。有一些现成的,例如http://www.codeproject.com/KB/cs/prettygoodsplashscreen.aspx

关于visual-studio - Visual Studio调试器的线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1242342/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com