0

经过 3 年的阅读,这是我在这里的第一篇文章。从来没有必要写一个。这是一个非常好的网站。


我有了扩展本机类以支持从、和AsyncTask调用的回调的想法。所以我不需要为每一个任务实现一个新的后代。RunInBackground()OnProgressUpdate()OnPreExecute()OnPostExecute()AsyncTask

(我不得不提到 inJava是一个被调用的方法DoInBackground(),它也存在于 Xamarin 端口中。但是文档说要覆盖RunInBackground()。)

目标是实例化AsyncTask后代,设置所需的回调并执行AsyncTask.

现在的问题是,我需要PublishProgress()从活动的回调内部调用以对不断变化的进度状态做出反应。所以我必须将此方法的单独回调传递给RunInBackground(). 但是当我这样做时,会抛出一个异常。

System.Reflection.TargetInvocationException:
调用的目标已引发异常。
---> 系统异常:
你调用的对象是空的

但我无法处理这个,因为我不知道应该需要哪个参考。调试清楚地表明回调是正确传递的。

活动:Main.cs

using AsyncSpecial = AsyncTaskEnhanced< System.String, System.Int32, System.Int32 >;

[ Activity( Label = "FooBar", MainLauncher = true ) ]
public class Main : Activity
{
  protected Int32 RunInBackground( AsyncSpecial.PublishProgressDelegate publishProgressCallback, params String[] arguments )
  {
    for ( Int32 n = 0; n < arguments.Length; n++ )
    {
      Console.WriteLine( "Item :: " + arguments[ n ] );
      // Won't invoke.
      PublishProgressDelegate( n );
      // Won't invoke.
      DelegateHelper.Invoke( publishProgressCallback, n );
    }
    return arguments.Length;
  }

  protected void OnProgressUpdate( Int32 progress )
  {
    Console.WriteLine( "Progress :: " + progress );
  }

  protected void OnPreExecute( )
  {
    Console.WriteLine( "Pre" );
  }

  protected void OnPostExecute( Int32 result )
  {
    Console.WriteLine( "Result :: " + result );
  }

  protected override void OnCreate( Bundle bundle )
  {
    base.OnCreate( bundle );
    this.SetContentView( Resource.Layout.Main );
    Button button = this.FindViewById< Button >( Resource.Id.btnOne );
    button.Click += ( Object sender, EventArgs eventArgs ) =>
    {
      AsyncSpecial asyncTask = new AsyncSpecial( );
      asyncTask.RunInBackgroundCallback = this.RunInBackground;
      asyncTask.OnProgressUpdateCallback = this.OnProgressUpdate;
      asyncTask.OnPreExecuteCallback = this.OnPreExecute;
      asyncTask.OnPostExecuteCallback = this.OnPostExecute;
      asyncTask.Execute( "ItemOne", "ItemTwo" );
    };
  }
}

类:AsyncTaskEnhanced.cs

public class AsyncTaskEnhanced< TArgument, TProgress, TResult > : AsyncTask< TArgument, TProgress, TResult >
{
  public delegate void PublishProgressDelegate( params TProgress[ ] progresses );
  public delegate TResult RunInBackgroundDelegate( PublishProgressDelegate publishProgressCallback, params TArgument[ ] arguments );
  public delegate void OnProgressUpdateDelegate( TProgress progress );
  public delegate void OnPreExecuteDelegate( );
  public delegate void OnPostExecuteDelegate( TResult result );

  private PublishProgressDelegate publishProgressCallback = null;
  public PublishProgressDelegate PublishProgressCallback
  { 
    get
    {
      return this.publishProgressCallback; 
    }
    set
    {
      this.publishProgressCallback = value; 
    }
  }

  private RunInBackgroundDelegate runInBackgroundCallback = null;
  public RunInBackgroundDelegate RunInBackgroundCallback
  { 
    get
    {
      return this.runInBackgroundCallback; 
    }
    set
    {
      this.runInBackgroundCallback = value; 
    }
  }

  private OnProgressUpdateDelegate onProgressUpdateCallback = null;
  public OnProgressUpdateDelegate OnProgressUpdateCallback
  { 
    get
    {
      return this.onProgressUpdateCallback; 
    }
    set
    {
      this.onProgressUpdateCallback = value; 
    }
  }

  private OnPreExecuteDelegate onPreExecuteCallback = null;
  public OnPreExecuteDelegate OnPreExecuteCallback
  { 
    get
    {
      return this.onPreExecuteCallback; 
    }
    set
    {
      this.onPreExecuteCallback = value; 
    }
  }

  private OnPostExecuteDelegate onPostExecuteCallback = null;
  public OnPostExecuteDelegate OnPostExecuteCallback
  { 
    get
    {
      return this.onPostExecuteCallback; 
    }
    set
    {
      this.onPostExecuteCallback = value; 
    }
  }

  public AsyncTaskEnhanced( IntPtr doNotUse, JniHandleOwnership transfer ) : base( doNotUse, transfer )
  {
    this.PublishProgressCallback = this.PublishProgress;
  }

  public AsyncTaskEnhanced( ) : base( )
  {
  }

  protected override TResult RunInBackground( params TArgument[ ] arguments )
  {
    TResult result = DelegateHelper.Invoke< TResult >( this.RunInBackgroundCallback, this.PublishProgressCallback, arguments );
    return result;
  }

  protected void OnProgressUpdate( TProgress progress )
  {
    DelegateHelper.Invoke( this.OnProgressUpdateCallback, progress );
  }

  protected override void OnPreExecute( )
  {
    DelegateHelper.Invoke( this.OnPreExecuteCallback );
  }

  protected override void OnPostExecute( TResult result )
  {
    DelegateHelper.Invoke( this.OnPostExecuteCallback, result );
  }
}

类:DelegateHelper.cs

static public class DelegateHelper
{
  static public void Invoke( Delegate callback, params Object[ ] arguments )
  {
    if ( null != callback )
    {
      callback.DynamicInvoke( arguments );
    }
  }

  static public TResult Invoke< TResult >( Delegate callback, params Object[ ] arguments )
  {
    TResult result = default( TResult );
    if ( null != callback )
    {
      result = ( TResult ) callback.DynamicInvoke( arguments );
    }
    return result;
  }
}

顺便说一句:如果我PublishProgress()从内部调用,AsyncTaskEnhanced::RunInBackground()AsyncTaskEnhanced::OnProgressUpdate()不会被调用。这让我很困惑。

我希望我让自己和我的需求足够清楚。

非常感谢。基督教

4

1 回答 1

0

对不起,我来晚了。正式工作是第一位的。正如@Cheesebaron 所建议的,我将我的第一个答案分开。


1.

好的。我解决了一个问题。我忘了PublishProgressCallbackAsyncTaskEnhanced. 因此,回调PublishProgress( n )中的第一次调用RunInBackground()正常工作,没有异常(除非它仍然没有调用OnProgressUpdate()),但是在调用期间DelegateHelper失败并出现

系统异常:
转换参数失败。

我得看看它。我的第一印象是它应该可以工作,这只是我必须弄清楚的一件简单的事情。


2.

没搞清楚,为什么PublishProgress()不调用OnPublishProgress()好像是Xamarin端口本身的问题。正如@Cheesebaron 进一步建议的那样,我使用了.NET 本机可能性。AsyncTask它们工作得很好,并且像课堂一样提供了更大的灵活性。

首先是委托助手,用于调用回调,无需显式代码内检查是否有任何处理程序附加到委托。

using System;

namespace Library
{
  static public class HDelegate
  {
    #region Methods

    static public void Invoke( Delegate callback, params Object[ ] arguments )
    {
      if ( null != callback )
      {
        callback.DynamicInvoke( arguments );
      }
    }

    static public TResult Invoke< TResult >( Delegate callback, params Object[ ] arguments )
    {
      TResult result = default( TResult );
      if ( null != callback )
      {
        result = ( TResult ) callback.DynamicInvoke( arguments );
      }
      return result;
    }

    #endregion
  }
}

这是AsyncTask克隆的实现。

using System;
using System.Threading;

namespace Library.Threading
{
  public class CallbackThread< TArgument, TProgress, TResult >
  {
    #region Delegates

    public delegate void PublishProgressDelegate( params TProgress[ ] progresses );
    public delegate TResult DoInBackgroundDelegate( PublishProgressDelegate publishProgressCallback, params TArgument[ ] arguments );
    public delegate void ProgressUpdateDelegate( TProgress progress );
    public delegate void PreExecuteDelegate( );
    public delegate void PostExecuteDelegate( TResult result );

    #endregion

    #region Properties

    private PublishProgressDelegate publishProgressCallback = null;
    protected virtual PublishProgressDelegate PublishProgressCallback
    { 
      get
      {
        return this.publishProgressCallback; 
      }
      set
      {
        this.publishProgressCallback = value; 
      }
    }

    private DoInBackgroundDelegate doInBackgroundCallback = null;
    public virtual DoInBackgroundDelegate DoInBackgroundCallback
    { 
      get
      {
        return this.doInBackgroundCallback; 
      }
      set
      {
        this.doInBackgroundCallback = value; 
      }
    }

    private ProgressUpdateDelegate progressUpdateCallback = null;
    public virtual ProgressUpdateDelegate ProgressUpdateCallback
    { 
      get
      {
        return this.progressUpdateCallback; 
      }
      set
      {
        this.progressUpdateCallback = value; 
      }
    }

    private PreExecuteDelegate preExecuteCallback = null;
    public virtual PreExecuteDelegate PreExecuteCallback
    { 
      get
      {
        return this.preExecuteCallback; 
      }
      set
      {
        this.preExecuteCallback = value; 
      }
    }

    private PostExecuteDelegate postExecuteCallback = null;
    public virtual PostExecuteDelegate PostExecuteCallback
    { 
      get
      {
        return this.postExecuteCallback; 
      }
      set
      {
        this.postExecuteCallback = value; 
      }
    }

    #endregion

    #region Constructors

    public CallbackThread( )
    {
      this.PublishProgressCallback = this.PublishProgress;
    }

    #endregion

    #region Methods

    protected virtual void PreExecute( )
    {
      HDelegate.Invoke( this.PreExecuteCallback );
    }

    protected virtual TResult DoInBackground( params TArgument[ ] arguments )
    {
      TResult result = HDelegate.Invoke< TResult >( this.DoInBackgroundCallback, this.PublishProgressCallback, arguments );
      return result;
    }

    protected virtual void PublishProgress( params TProgress[ ] progresses )
    {
      foreach ( TProgress progress in progresses )
      {
        this.ProgressUpdate( progress );
      }
    }

    protected virtual void ProgressUpdate( TProgress progress )
    {
      HDelegate.Invoke( this.ProgressUpdateCallback, progress );
    }

    protected virtual void PostExecute( TResult result )
    {
      HDelegate.Invoke( this.PostExecuteCallback, result );
    }

    public virtual void Execute( params TArgument[ ] arguments )
    {
      Thread thread = new Thread(( ) =>
      {
        this.PreExecute( );
        TResult result = this.DoInBackground( arguments );
        this.PostExecute( result );
      } );
      thread.Start( );
    }

    #endregion
  }
}

HDelegateCallbackThread确保实现最简单的需求。但它们也带来了一些好处。现在可以将一种实现用于多种目的,同时可以使用回调。这些回调也是多委托。所以可以在链中调用几个动作。

于 2013-05-21T10:45:31.687 回答