1

ここには 2 つの例外があります。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...";
            }));

このフラグメントがコメント アウトされている場合、次の問題が発生します。プログラム レベルでのTargetInvocationException です。

この内部例外はInvalidOperationExceptionです。

コードは非常に単純なので、これを実装するのは難しいことではありません。先に進むためのいくつかの新しいヒントだけです。

Visual Studio プロジェクト ファイル

4

1 に答える 1

2

ユーザーが終了ボタンを押すと、Close()メソッドが呼び出され、UIが破棄され始めます。ただし、ワーカーコードは実行を継続し、UIを更新しようとしますが、これは実行できなくなります。

これらすべての呼び出し呼び出しを一元化する場合:

public void UpdateUI(Action action) {
    if(!Exiting) this.Invoke(action);
}

あなたは呼び出すことができます:

UpdateUI(() =>
        {
            toolStripProgressBar1.Increment(1);
            toolStripStatusLabel1.Text = "Processing...";
        });

(etc-代わりにすべてのthis.Invoke呼び出しを使用する必要がありますUpdateUI)そしてそれは機能するはずです。また、Exiting揮発性にします。

于 2009-03-22T07:25:32.247 に答える