gpt4 book ai didi

c# - 事件处理程序不再触发

转载 作者:太空宇宙 更新时间:2023-11-03 22:08:18 24 4
gpt4 key购买 nike

我今天下午一直在工作,试图使用后台 worker 从位于我的程序集中的一个非常大的 xml 文件中读取。在我决定重命名 backgroundworker 的对象名称之前,它一直运行良好。在我构建解决方案后,它告诉我它是成功的。运行我的程序并对其进行测试后,我注意到后台工作人员的 DoWork 事件根本拒绝触发。当我将下面的代码添加到 Backgroundworker 的 RunWorkerCompleted 事件时,我得到的只是一个消息框,里面什么都没有。 MessageBox.Show(e.Result + ""+ e.Error); 将其重命名为原来的名称也无济于事。我自己编写了所有代码,因此这里没有涉及第三方应用程序。

这是我用来设置后台工作的代码

private volatile List<string> listItems = new List<string>();
private BackgroundWorker _populateListItems = new BackgroundWorker();
private string currentConnection;
#endregion
public frmSettings()
{
InitializeComponent();

//I will be able to track how far the list is populated with the following command.
_populateListItems.WorkerReportsProgress = true;
//This will fire if there is an error in the xml file.
_populateListItems.WorkerSupportsCancellation = true;
//Assign the job to be done for the backgroundworker
_populateListItems.DoWork +=new DoWorkEventHandler(_populateListItems_DoWork);
_populateListItems.ProgressChanged += new ProgressChangedEventHandler(_populateListItems_ProgressChanged);
//When the worker is finished, the following event will fire: All UI controls will be updated.
_populateListItems.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_populateListItems_RunWorkerCompleted);

_populateListItems.RunWorkerAsync();
}

void _populateListItems_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
prgProgress.Value = e.ProgressPercentage;
lblProgress.Text = e.ProgressPercentage.ToString() + "%";
}

private void _populateListItems_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//The operation is completed/Cancelled/Erroneous. The list will now be populated with the available information.
MessageBox.Show(e.Result + " " + e.Error);
foreach (string item in listItems)
{
liConnections.Items.Add(item);
}

//This shows the user which connection is currently used.
lblCurrentSelection.Text = currentConnection;
}

private void _populateListItems_DoWork(object sender, DoWorkEventArgs e)
{
try
{
//The following lines of code are the variables that are going to be used.
// xReadSettings will make the XmlReader xRead Ignore whitespaces and comments, if any.
// assemblyExecuted will get information from which assembly gets Executed.
// filename Will get the filename of the settings.xml file that is going to be used.
// SettingsStream will open the stream for reading and writing, using the GetManifestResourceStream() method from the currently executed assembly.
XmlReaderSettings xReadSettings = new XmlReaderSettings();
Assembly assemblyExecuted = Assembly.GetExecutingAssembly();
string filename = String.Format("{0}.Settings.xml", assemblyExecuted.GetName().Name);
Stream settingsStream = assemblyExecuted.GetManifestResourceStream(filename);

xReadSettings.IgnoreComments = true;
xReadSettings.IgnoreWhitespace = true;

//Finally the xmlReader object is created using the settingstream, and its settings.
//While the stream reads, it checks whether the nodes accessed are elements of the xml file.
//if it is an element that is accessed, then we check whether the element which is accessed is a connection string to the database
//if it is a connectionstring to the database, we will check if the connection has a name.
//if it has a name, we get the name attribute, and add it to our list. The list is volatile, so it will be up to date, because this
//background thread is updating it.
//To Update the progress of the backgroundworker, we need to know the amount of elements in the XML File. Xpath will be used for this.
XmlDocument xdoc = new XmlDocument();
xdoc.Load(settingsStream);
XmlNodeList nodes = xdoc.SelectNodes("*"); //Xpath - select all.
int totalElementsToRead = nodes.Count;
int totalElementsRead = 0;
using (XmlReader xRead = XmlReader.Create(settingsStream, xReadSettings))
{
while (xRead.Read())
{
if (xRead.NodeType == XmlNodeType.Element)
{
if (xRead.Name == "ConnectionString")
{
if (xRead.HasAttributes)
{
string attribute = xRead.GetAttribute("name").ToString();
listItems.Add(attribute);
}
}
if (xRead.Name == "CurrentConnection")
{
xRead.Read(); //gets the value of <CurrentConnection>
currentConnection = xRead.Value.Trim();
}
totalElementsRead++;
_populateListItems.ReportProgress(totalElementsRead / totalElementsToRead * 100);
}
}
}
}
catch
{
_populateListItems.CancelAsync();
}
}

请原谅其背后评论中的理论。我正在尽我所能解释它。

不过我的问题是,任何人都可以看出哪里出了问题吗?为什么事件突然不触发?它应该用我的 xml 文件中的项目填充一个列表(未触及,在重命名之前正在工作)。运行逐步调试也证明它正在跳过我的 doWork 事件处理程序。

最佳答案

我认为问题在于您正在从构造函数调用 RunWorkerAsync 并且 ProgressChanged 由于表单尚不可见而失败。尝试将对 RunWorkerAsync 的调用移动到表单的 Show 事件处理程序。

好的,所以问题是 DoWork 事件处理程序中的异常被 try..catch block 吞噬

总结您的代码存在的问题:

  • try..catch block 吃掉所有异常并使调试变得困难。
  • 从表单构造函数内部调用 RunWorkerAsync
  • 在没有适当同步/锁定的情况下从工作线程访问 UI 线程对象。
  • DoWork 事件处理程序中调用 CancelAsync

关于c# - 事件处理程序不再触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7621353/

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