我的目的是写一个下载网页的类,类写好以后在运行的时候出错。
调用public void DoDownload(string BaseUrl, string RelativeUrl)这个函数的时候,直接跳到程序的入口点Application.Run(new Form1())报出错了。

未处理TargetInvocationException
调用的目标发生了异常。

InnerException的Message是:未将对象引用设置到对象的实例。
完整的错误信息附在后面。
namespace Download
{
    public enum DownloadStatus
    {
        Success, Failed, Canceled
    }    public struct DownloadArgs
    {
        public Int32 Identifier;
        public string SourceUrl;
        public string Result;
        public DownloadStatus Status;
        public Exception Error;
    }    public delegate void DownLoadCompleteHandle(object sender, DownloadArgs e);
    public delegate void DownloadProgressChangedHandle(object sender, System.Net.DownloadProgressChangedEventArgs e);    public class Download
    {
        public event DownLoadCompleteHandle DownloadComplete;
        public event DownloadProgressChangedHandle DownloadProgressChanged;        Int32 iIdentifier;
        System.Net.WebClient wcDownload;
        string sSourceUrl;        public Download(Int32 Identifier)
        {
            iIdentifier = Identifier;
            wcDownload = new System.Net.WebClient();
            wcDownload.Encoding = System.Text.Encoding.UTF8;
            wcDownload.DownloadProgressChanged += new System.Net.DownloadProgressChangedEventHandler(wcDownload_DownloadProgressChanged);
            wcDownload.DownloadStringCompleted += new System.Net.DownloadStringCompletedEventHandler(wcDownload_DownloadStringCompleted);
        }        void wcDownload_DownloadStringCompleted(object sender, System.Net.DownloadStringCompletedEventArgs e)
        {
            DownloadArgs daT = new DownloadArgs();
            daT.SourceUrl = sSourceUrl;
            if (e.Error != null)
            {
                daT.Status = DownloadStatus.Failed;
                daT.Error = e.Error;
            }
            else
            {
                if (e.Cancelled)
                {
                    daT.Status = DownloadStatus.Canceled;
                }
                else
                {
                    daT.Identifier = iIdentifier;
                    daT.Result = System.Text.Encoding.Default.GetString(System.Text.Encoding.UTF8.GetBytes(e.Result));
                    daT.Status = DownloadStatus.Success;
                }
            }
            DownloadComplete(sender, daT);
        }        void wcDownload_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e)
        {
            DownloadProgressChanged(sender, e);
        }        public void DoDownload(string BaseUrl, string RelativeUrl)
        {
            System.Uri uri;
            if (BaseUrl.Length > 0)
            {
                if (System.Uri.TryCreate(new Uri(BaseUrl), RelativeUrl, out uri))
                {
                    sSourceUrl = uri.AbsoluteUri;
                }
            }
            else
            {
                sSourceUrl = RelativeUrl;
            }
            wcDownload.DownloadStringAsync(new Uri(sSourceUrl));
        }        public bool IsBusy
        {
            get
            {
                return wcDownload.IsBusy;
            }
        }
    }
}完整错误信息:
未处理 System.Reflection.TargetInvocationException
  Message="调用的目标发生了异常。"
  Source="mscorlib"
  StackTrace:
       在 System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
       在 System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
       在 System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
       在 System.Delegate.DynamicInvokeImpl(Object[] args)
       在 System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
       在 System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
       在 System.Threading.ExecutionContext.runTryCode(Object userData)
       在 System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
       在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
       在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       在 System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
       在 System.Windows.Forms.Control.InvokeMarshaledCallbacks()
       在 System.Windows.Forms.Control.WndProc(Message& m)
       在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       在 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       在 System.Windows.Forms.Application.Run(Form mainForm)
       在 Test.Program.Main() 位置 E:\Visual Studio 2005\Test\Test\Program.cs:行号 17
       在 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       在 System.Threading.ThreadHelper.ThreadStart()

解决方案 »

  1.   

    上面的代码如果把
    wcDownload.DownloadProgressChanged += new System.Net.DownloadProgressChangedEventHandler(wcDownload_DownloadProgressChanged); 
    这行删掉就不会报错了。就是说,我不能定阅DownloadProgressChanged 这个事件。Why?
      

  2.   

            public Download(Int32 Identifier)
            {
                iIdentifier = Identifier;
                wcDownload = new System.Net.WebClient();
                wcDownload.Encoding = System.Text.Encoding.UTF8;
                wcDownload.DownloadProgressChanged += new System.Net.DownloadProgressChangedEventHandler(wcDownload_DownloadProgressChanged);
                wcDownload.DownloadStringCompleted += new System.Net.DownloadStringCompletedEventHandler(wcDownload_DownloadStringCompleted);
            } 这里最后要加wcDowload.DownloadData或DownloadString(url)吧
      

  3.   

    1 如果你的Download调用者没有处理DownloadProgressChanged事件,那么在DownloadProgressChanged(sender, e);出错(DownloadProgressChanged对像为空) 
    void wcDownload_DownloadProgressChanged(object sender, System.Net.DownloadProgressChangedEventArgs e)
            {
                // DownloadProgressChanged(sender, e); <-- 空
    // 改为
    if (DownloadProgressChanged != null) 
      DownloadProgressChanged(sender, e);
            } 2 你处理了Download.DownloadProgressChanged事件,并在这个事件中处理UI更新。这时会出现多线程更新UI的问题。
      

  4.   

    请教下,关于第1第一点的。为什么Download调用者没有处理DownloadProgressChanged事件时,DownloadProgressChanged会是空值呢?
    第2点就没什么问题了,一个lock就解决了。