开发者

In c# how should an async completed event access properties of the calling class?

开发者 https://www.devze.com 2023-01-29 11:48 出处:网络
We have been using lamda events like this: bookMarkClient.wmdeleteCompleted += (s, ea) => { if (ea.Result = \"Success\")

We have been using lamda events like this:

bookMarkClient.wmdeleteCompleted += (s, ea) =>
        {
            if (ea.Result = "Success")
            {
                foreach (BookMark bookMark in BookMarks)
                    {
                        if (bookMarkId == bookMark.bm_id)
                        {
                            BookMarks.Remove(bookMark);
                            OnNotifyPropertyChanged("BookMarks");
                            break;
                        }
                    }                
               }
        };

        bookMarkClient.wmdeleteBookMarkAsync(bookMarkId);

However according to many answers on stackoverflow these can not be removed, such that if I call this code again my event is fired twice. So I want to remove the lambda code and do this:

//in the class constructor
bookMarkClient.wmdeleteBookMarkCompleted += new EventHandler<wmdeleteBookMarkCompletedEventArgs>(bookMarkClient_wmdeleteBookMarkCompleted);

//Proc on the same class
 void bookMarkClient_wmdeleteBookMarkCompleted(object sender, wmdeleteBookMarkCompletedEventArgs e)
        {
            if (ea.Result = "Success")
            {
                foreach (BookMark bookMark in BookMarks)
                {
                   if (bookMarkId == bookMark.bm_id)
                    {
                        BookMarks.Remove(bookMark);
                        OnNotifyPropertyChanged("BookMarks");
                        break;
                    }
                }
            }

              }

//on button click
bookMarkClient.wmdeleteBookMarkAsync(bookMarkId);

HOWEVER: the variable bookMarkId is no longer available. I understand this is because the lambda event copies the variable in to the constructed class and keeps it alive for the duration of the event. So how do I do the same?

I've tried setting a private variable but test show this can be changed before the call back is received! This would also apply to the collection called Bookmarks.

Note, This is a Silverlight client and I'd rather not pass back the Id/collection in the event args as this would mean reworking lots of wcf code.

Many Thanks, Matt

ps first post to stack so take it easy 开发者_如何学Con me...


Store the event handler in a local variable; then you can add and remove the same event handler:

EventHandler<wmdeleteBookMarkCompletedEventArgs> handler = (s, ea) => { .... }
bookMarkClient.wmdeleteBookMarkCompleted += handler;
// ...
bookMarkClient.wmdeleteBookMarkCompleted -= handler;

Alternatively, a lambda expression is just syntactic sugar for a compiler-generated nested class. If you can't add the bookmark ID to the EventArgs, simulate a lambda by creating your own class:

BookmarkDeletedListener listener = new BookmarkDeletedListener(this, bookMarkId);
bookMarkClient.wmdeleteBookMarkCompleted += listener.DeleteBookmarkCompleted;
bookMarkClient.wmdeleteBookMarkCompleted -= listener.DeleteBookmarkCompleted;

// ...

class BookmarkDeletedListener
{
    public BookmarkDeletedListener(ParentClass parent, string bookmarkId)
    {
        _parent = parent;
        _bookmarkId = bookmarkId;
    }

    public DeleteBookmarkCompleted(object sender, wmdeleteBookMarkCompletedEventArgs e)
    {
        if (ea.Result = "Success")
        {
            foreach (BookMark bookMark in BookMarks)
            {
                if (_bookmarkId == bookMark.bm_id)
                {
                    _parent.BookMarks.Remove(bookMark);
                    _parent.OnNotifyPropertyChanged("BookMarks");
                    break;
                }
            }
        }
    }

    readonly ParentClass _parent;
    readonly string _bookmarkId;
}


You can remove a lambda, AFAIK, as long as you hold onto it. It can even remove itself when fired:

Action<object, wmdeleteBookMarkCompletedEventArgs> handler;
handler =
    (s, ea) =>
        {
            bookMarkClient.wmdeleteCompleted -= handler;
            if (ea.Result == "Success")
            ...
        };

bookMarkClient.wmdeleteCompleted += handler;
0

精彩评论

暂无评论...
验证码 换一张
取 消