在 Windows 窗体中使用 PFX 时出现 InvalidOperationException
我这里有两个例外。 不知道为什么会发生,因为我使用 Form.Invoke 在 UI 线程上运行 UI 更新。 首先,
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml;
using System.Windows.Forms;
namespace Toplr
{
using System.Collections.Specialized;
using System.Xml.XPath;
using System.Xml.Linq;
using System.Text;
using System.ServiceModel.Web;
using System.ServiceModel.Syndication;
using System.Net;
using System.Web;
using System.Xml.Schema;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
public partial class ToplrForm : Form
{
private readonly Uri SearchBase = new Uri(@"http://www.twine.com/feed/atom/entries/");
private readonly UriTemplate SearchTemplate = new UriTemplate(@"search?type={type}&author={author}");
public ToplrForm()
{
InitializeComponent();
Exiting = false;
TaskContext = new TaskManager();
Items = new AsyncBindingList<Twine>(this);
twineBindingSource.DataSource = Items;
}
private void ToplrForm_Load(object sender, EventArgs e)
{
}
private readonly TaskManager TaskContext;
private readonly AsyncBindingList<Twine> Items;
private bool Exiting;
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Close()");
Close();
}
private void ToplrForm_FormClosing(object sender, FormClosingEventArgs e)
{
MessageBox.Show("Exiting = tru");
Exiting = true;
//TaskContext.Dispose();
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
var sfd = new SaveFileDialog()
{
ValidateNames = true
};
if (sfd.ShowDialog() == DialogResult.OK)
{
using (var xtw = new XmlTextWriter(sfd.FileName, Encoding.UTF8))
{
var xw = XmlWriter.Create(xtw);
xw.WriteStartDocument();
xw.WriteStartElement("opml");
xw.WriteAttributeString("version", "1.1");
xw.WriteStartElement("head");
xw.WriteElementString("title", userNameComboBox.Text);
xw.WriteEndElement();
xw.WriteStartElement("body");
foreach (var row in twineDataGridView.SelectedRows)
{
var twine = (Twine)((DataGridViewRow)row).DataBoundItem;
if (twine != null)
{
xw.WriteStartElement("outline");
xw.WriteAttributeString("text", twine.Title);
xw.WriteAttributeString("type", "link");
xw.WriteAttributeString("url", twine.HtmlAddress);
xw.WriteStartElement("outline");
xw.WriteAttributeString("text", twine.Title);
xw.WriteAttributeString("type", "atom");
xw.WriteAttributeString("url", twine.AtomAddress);
xw.WriteEndElement();
xw.WriteEndElement();
}
}
xw.WriteEndElement();
xw.WriteEndElement();
xw.WriteEndDocument();
xw.Close();
}
}
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Copyright (C) 2009 Bent Rasmussen");
}
private void accessButton_Click(object sender, EventArgs e)
{
var user = userNameComboBox.Text;
Task.Create(x => ProcessAccount(user));
}
public void ProcessAccount(string user)
{
this.Invoke((Action)(() =>
{
userNameComboBox.Enabled = false;
accessButton.Enabled = false;
toolStripStatusLabel1.Text = "Processing...";
}));
var param = new NameValueCollection();
param.Add("type", "Twine");
param.Add("author", user);
var source = SearchTemplate.BindByName(SearchBase, param);
var wc = new WebClient();
using (var feedStream = wc.OpenRead(source))
{
var reader = XmlReader.Create(feedStream);
var feed = SyndicationFeed.Load(reader);
int c = 0, i = 0;
foreach (var item in feed.Items)
{
this.Invoke((Action)(() =>
{
toolStripProgressBar1.Increment(1);
toolStripStatusLabel1.Text = "Processing...";
}));
if (item.Links.Count != 0)
{
//try
{
ProcessTwine(item);
i++;
}
//catch (Exception)
{
c++;
}
}
if (Exiting)
break;
}
}
this.Invoke((Action)(() =>
{
userNameComboBox.Enabled = true;
accessButton.Enabled = true;
}));
}
private Twine ProcessTwine(SyndicationItem item)
{
var result = new Twine();
result.Title = item.Title.Text;
result.HtmlAddress = item.Links[0].Uri.ToString();
result.AtomAddress = "";
var wc = new WebClient();
var data = wc.DownloadData(result.HtmlAddress);
var stream = new MemoryStream(data);
var readerSettings = new XmlReaderSettings()
{
ProhibitDtd = false,
ValidationType = ValidationType.None,
ValidationFlags = XmlSchemaValidationFlags.None,
};
var reader = XmlReader.Create(stream, readerSettings);
var doc = XDocument.Load(reader);
var htmlNs = (XNamespace)"http://www.w3.org/1999/xhtml";
var root = doc.Root;
var atom = from r in root.Descendants(htmlNs + "head").Descendants(htmlNs + "link")
where r.Attribute("rel").Value == "alternate" && r.Attribute("type").Value == "application/atom+xml"
select r.Attribute("href");
foreach (var e in atom)
{
if (e.Value != "")
{
result.AtomAddress = e.Value;
this.BeginInvoke((Action)(() =>
{
Items.Add(result);
toolStripProgressBar1.Increment(1);
}));
}
break;
}
return result;
}
}
}
这会触发此片段上的异常“无法访问已处置的对象”
this.Invoke((Action)(() =>
{
toolStripProgressBar1.Increment(1);
toolStripStatusLabel1.Text = "Processing...";
}));
如果此片段被注释掉,我会遇到下一个问题 - 程序级别的 TargetInitationException 。
其内部异常是InvalidOperationException。
代码非常简单,所以实现它应该不难,我只是添加了一些提示以继续前进。
I have two exceptions here. Not sure why they occur because I use Form.Invoke to run UI updates on the UI thread. So first,
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml;
using System.Windows.Forms;
namespace Toplr
{
using System.Collections.Specialized;
using System.Xml.XPath;
using System.Xml.Linq;
using System.Text;
using System.ServiceModel.Web;
using System.ServiceModel.Syndication;
using System.Net;
using System.Web;
using System.Xml.Schema;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
public partial class ToplrForm : Form
{
private readonly Uri SearchBase = new Uri(@"http://www.twine.com/feed/atom/entries/");
private readonly UriTemplate SearchTemplate = new UriTemplate(@"search?type={type}&author={author}");
public ToplrForm()
{
InitializeComponent();
Exiting = false;
TaskContext = new TaskManager();
Items = new AsyncBindingList<Twine>(this);
twineBindingSource.DataSource = Items;
}
private void ToplrForm_Load(object sender, EventArgs e)
{
}
private readonly TaskManager TaskContext;
private readonly AsyncBindingList<Twine> Items;
private bool Exiting;
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Close()");
Close();
}
private void ToplrForm_FormClosing(object sender, FormClosingEventArgs e)
{
MessageBox.Show("Exiting = tru");
Exiting = true;
//TaskContext.Dispose();
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
var sfd = new SaveFileDialog()
{
ValidateNames = true
};
if (sfd.ShowDialog() == DialogResult.OK)
{
using (var xtw = new XmlTextWriter(sfd.FileName, Encoding.UTF8))
{
var xw = XmlWriter.Create(xtw);
xw.WriteStartDocument();
xw.WriteStartElement("opml");
xw.WriteAttributeString("version", "1.1");
xw.WriteStartElement("head");
xw.WriteElementString("title", userNameComboBox.Text);
xw.WriteEndElement();
xw.WriteStartElement("body");
foreach (var row in twineDataGridView.SelectedRows)
{
var twine = (Twine)((DataGridViewRow)row).DataBoundItem;
if (twine != null)
{
xw.WriteStartElement("outline");
xw.WriteAttributeString("text", twine.Title);
xw.WriteAttributeString("type", "link");
xw.WriteAttributeString("url", twine.HtmlAddress);
xw.WriteStartElement("outline");
xw.WriteAttributeString("text", twine.Title);
xw.WriteAttributeString("type", "atom");
xw.WriteAttributeString("url", twine.AtomAddress);
xw.WriteEndElement();
xw.WriteEndElement();
}
}
xw.WriteEndElement();
xw.WriteEndElement();
xw.WriteEndDocument();
xw.Close();
}
}
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Copyright (C) 2009 Bent Rasmussen");
}
private void accessButton_Click(object sender, EventArgs e)
{
var user = userNameComboBox.Text;
Task.Create(x => ProcessAccount(user));
}
public void ProcessAccount(string user)
{
this.Invoke((Action)(() =>
{
userNameComboBox.Enabled = false;
accessButton.Enabled = false;
toolStripStatusLabel1.Text = "Processing...";
}));
var param = new NameValueCollection();
param.Add("type", "Twine");
param.Add("author", user);
var source = SearchTemplate.BindByName(SearchBase, param);
var wc = new WebClient();
using (var feedStream = wc.OpenRead(source))
{
var reader = XmlReader.Create(feedStream);
var feed = SyndicationFeed.Load(reader);
int c = 0, i = 0;
foreach (var item in feed.Items)
{
this.Invoke((Action)(() =>
{
toolStripProgressBar1.Increment(1);
toolStripStatusLabel1.Text = "Processing...";
}));
if (item.Links.Count != 0)
{
//try
{
ProcessTwine(item);
i++;
}
//catch (Exception)
{
c++;
}
}
if (Exiting)
break;
}
}
this.Invoke((Action)(() =>
{
userNameComboBox.Enabled = true;
accessButton.Enabled = true;
}));
}
private Twine ProcessTwine(SyndicationItem item)
{
var result = new Twine();
result.Title = item.Title.Text;
result.HtmlAddress = item.Links[0].Uri.ToString();
result.AtomAddress = "";
var wc = new WebClient();
var data = wc.DownloadData(result.HtmlAddress);
var stream = new MemoryStream(data);
var readerSettings = new XmlReaderSettings()
{
ProhibitDtd = false,
ValidationType = ValidationType.None,
ValidationFlags = XmlSchemaValidationFlags.None,
};
var reader = XmlReader.Create(stream, readerSettings);
var doc = XDocument.Load(reader);
var htmlNs = (XNamespace)"http://www.w3.org/1999/xhtml";
var root = doc.Root;
var atom = from r in root.Descendants(htmlNs + "head").Descendants(htmlNs + "link")
where r.Attribute("rel").Value == "alternate" && r.Attribute("type").Value == "application/atom+xml"
select r.Attribute("href");
foreach (var e in atom)
{
if (e.Value != "")
{
result.AtomAddress = e.Value;
this.BeginInvoke((Action)(() =>
{
Items.Add(result);
toolStripProgressBar1.Increment(1);
}));
}
break;
}
return result;
}
}
}
This triggers the exception "Cannot access a disposed object" on this fragment
this.Invoke((Action)(() =>
{
toolStripProgressBar1.Increment(1);
toolStripStatusLabel1.Text = "Processing...";
}));
If this fragment is commented out, I run into the next problem - a TargetInvocationException on Program level.
The inner exception of this is an InvalidOperationException.
The code is quite simple, so it should not be hard to implement this, I just new a few hints to move on.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果用户点击退出按钮,就会调用
Close()
方法,并且 UI 开始被拆除。 但是,您的工作代码会继续运行并尝试更新 UI,但它无法再执行此操作。如果集中所有这些调用:
您可以调用:(
等等 - 所有
this.Invoke
调用应使用UpdateUI
代替)它应该有效。 另外,使
Exiting
可变。If the user hits the exit button, the
Close()
method is called, and the UI starts getting torn down. However, your worker code keeps running and attempts to update the UI, which it can no longer do.If you centralise all those invoke calls:
you can call:
(etc - all the
this.Invoke
calls should useUpdateUI
instead)and it should work. Also, make
Exiting
volatile.