2009-03-22 6 views
1

У меня есть два исключения здесь. Не знаю, почему они возникают, потому что я использую Form.Invoke для запуска обновлений пользовательского интерфейса в потоке пользовательского интерфейса. Так первое,InvalidOperationException с использованием PFX с формами Windows

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 project files.

ответ

2

Если пользователь нажимает кнопку выхода, вызывается метод Close(), и пользовательский интерфейс начинает срываться. Однако ваш рабочий код продолжает работать и пытается обновить пользовательский интерфейс, который он больше не может выполнять.

Если вы централизовать все те вызовы вызова:

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

вы можете позвонить:

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

(и т.д. - все this.Invoke вызовы должны использовать UpdateUI вместо) и он должен работать. Кроме того, сделать Exiting volatile.

+0

Спасибо, Марк, это хорошая идея! Однако это не совсем решает фундаментальную проблему. Я все еще получаю InvalidOperationException. –

+0

Я не уверен, что это связано с тем, что я использую параллельные расширения. У новой версии .Net 4.0 будет отмена, я определенно буду использовать ее, но это тоже самое. –

+0

Кроме того, что касается проблемы утилизации - почему это произойдет, учитывая, что на практике я не закрыл приложение, это происходит, когда он работает. Все, что я в основном сделал, это нажать кнопку, чтобы начать сканирование. –