我在这里读到关于代表和事件(完全不同的原因)来自这个[网站] [1]在那里我得到的印象是,如果你的事件需要足够长的时间,就会生成一个单独的线程.那让我想到了一个我似乎无法解决的错误.所以我正在为我的MSR设备制作键盘楔程序,通过RS232端口进行通信.我创建了这个类来处理输入.
public ComPortInput(SerialPort sp, int delay)
: this(delay)
{
if (sp == null)
throw new System.ArgumentNullException("Serial port can not be null");
serialPort = sp;
}
Run Code Online (Sandbox Code Playgroud)
当我打开这个ComPortInput类时,我订阅了DataReceived事件.如果我正确猜测,那么如果我将延迟设置得足够高,那么我的dataevent将创建一个新线程.我认为通过查看我的代码可以最好地描述问题.
Program.cs中
[STAThread]
static void Main()
{
singleton = new System.Threading.Mutex(true, "Keymon");
if (!singleton.WaitOne(System.TimeSpan.Zero, true))
{ return; }
InstantiateProgram();
System.Windows.Forms.Application.Run(main);
}
private static void InstantiateProgram()
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
main = new frmMain();
}
Run Code Online (Sandbox Code Playgroud)
ComPortInput.cs.只是datareceived事件
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (Delay > 0)
System.Threading.Thread.Sleep(Delay); //waits for all the data to be sent to …Run Code Online (Sandbox Code Playgroud) 在vb.net WebService中查找内存泄漏时,我检测到阻塞的终结器,以及从未发布的几个对象(例如System.Threading.ReaderWriterLock)
Google告诉我这可能是因为STAThread属性是在我的main方法上设置的.我花了很长时间才发现VB.net使用STA作为默认值,而c#使用MTA.
当我将MTAThread-Attribute添加到我的Main方法时,一切正常,对象被释放.因此,如果我理解正确,则在STA模式中阻止Finalizer-Thread.
到目前为止一切顺利,但说实话,我今天第一次听说STA和MTA.可以在没有任何想法的情况下在STA和MTA之间切换吗?
更新 我仍然不确定我是否可以在不破坏我的代码的情况下在MTA和STA之间切换.这是一些更多的想法
不久前,我们使用IronPython将Python脚本添加到Wpf应用程序中.起初,它只是"奴隶",因为例如按钮点击调用脚本然后只是运行完成将控制权返回给Wpf.后来我们添加了'master'脚本:脚本在它自己的线程中运行,并控制应用程序的其余部分.这是相当具有挑战性的,但过了一段时间,在现有的SO内容的帮助下,我们看起来很有效.从来没有真正使用它,直到现在,不幸的是事实证明它不能正常工作.核心原因是虽然有两个单独的STA线程(主要的Wpf一个和一个脚本),因此两个不同的Dispatcher实例,主线程似乎被阻止,因为脚本线程在循环中等待主线程完成(响应在脚本线程上处理的按钮单击并在主线程上启动事件).使用具有单独ui窗口的两个线程的全部意义当然不会发生.到底是怎么回事?
更新它是可重复使用最少的代码,所以我链接到它而不是在这里发布伪代码.在创建代码时,我发现当脚本线程创建的窗口未嵌入(设置MainWindow.hostedWin = false)时,不会发生死锁,并且一切都按预期运行.
回应评论所以有3个关注的线程发挥作用.我们称它们为Python,Ui和Process.Python启动Process并等待它完成.进程调用在Ui上调用.在那一点上不应该做任何事情:毕竟,它是阻塞的Python,而不是Ui,而这个结构的重点是Ui不应该与Python交互.好吧,除了它确实以某种方式.哪个是罪魁祸首.在僵局中,Ui坐在那里,PresentationFramework.dll!System.Windows.Interop.HwndHost.OnWindowPositionChanged(System.Windows.Rect rcBoundingBox) + 0x82 bytes而Process坐在WindowsBase.dll!System.Windows.Threading.DispatcherOperation.DispatcherOperationEvent.WaitOne() + 0x2f bytes那里,而Python就在Thread.Sleep.
这里发生了什么,以及如何解决它?
经过2个小时的研究,我仍然找不到解决我的问题的方法。
我所做的任务是在 BackGroundWorker 线程中处理一些文件。但是,有时我需要使用 ShowDialog 让用户选择 SaveFile 位置,但我收到 STA/MTA 错误。
主窗体代码:
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = false;
ProcessReportWorker.RunWorkerAsync();
}
Run Code Online (Sandbox Code Playgroud)
工作代码:
void ProcessReportWorker_DoWork(object sender, DoWorkEventArgs e)
{
int ReportCount = Reports.Count();
foreach (string Report in Reports)
{
ProcessReport NewReport = new ProcessReport(Report);
string result = NewReport.Start();
}
}
Run Code Online (Sandbox Code Playgroud)
ProcessReport.Start() 代码:
class ProcessReport
{
public string Start()
{
if(File.Exists(ResultPath))
{
SaveFileDialog SaveReport = new SaveFileDialog();
SaveReport.InitialDirectory = "c:\somepath";
SaveReport.CheckPathExists = true;
SaveReport.DefaultExt = ".xls";
SaveReport.OverwritePrompt = true;
SaveReport.ValidateNames …Run Code Online (Sandbox Code Playgroud) 我正在尝试用纯 C# 打开一个窗口。为此,我创建了一个窗口构造函数 ( SGFWindow) ,该窗口构造Window函数从以下位置扩展了该类System.Windows:
namespace SGF
{
public partial class SGFWindow : Window
{
public SGFWindow()
{
this.Title = "SGF Window";
this.Width = 200;
this.Height = 200;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我创建了一个WindowTest类来测试它:
namespace SGF
{
public class WindowTest
{
public static void Main(string[] args)
{
SGFWindow window = new SGFWindow();
window.Show();
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是,我收到“调用线程必须是 STA,因为许多 UI 组件都需要这个”。错误 ; 只不过这不是一个线程(或者不是我创建的线程?)。
我搜索了它,但它总是关于一个线程,我找不到如何修复这个错误。我也看到过一些东西[STAThread],但显然不适合它。
预先感谢,马索。
c# ×5
sta ×5
mta ×2
wpf ×2
dispatcher ×1
events ×1
ironpython ×1
polymorphism ×1
showdialog ×1
vb.net ×1