简体   繁体   English

Task.Run中的实例变量为null

[英]Instance variable is null inside Task.Run

UPDATE: 更新:

public MobileServiceUser CurrentMsUser { get; private set; } 

I have an instance property CurrentMsUser which is populated and I'm trying to reference it within an async method, but for some reason it is null in the method. 我有一个实例属性CurrentMsUser ,该属性已填充,并且我正在尝试在异步方法中引用它,但由于某种原因,该方法在该方法中为null。 I've set a breakpoint on the property setter and it never is set to null, so I'm fairly certain the property never becomes null. 我已经在属性设置器上设置了一个断点,并且从未将其设置为null,所以我可以肯定地确定该属性永远不会为null。 After the async method returns it's present again. 异步方法返回后,它再次出现。 It seems as soon as I'm within the anonymous async method I can't access the property. 似乎一旦进入匿名异步方法,就无法访​​问该属性。 Here is my method: 这是我的方法:

public async Task CreateOrRetrieveAppUserAsync()
{
    await Task.Run (async () => {
        try {
            var usersCollection = await _userTable.ToCollectionAsync ();
            var users = usersCollection.
                Where(x =>
                    x.FacebookToken == CurrentMsUser.UserId).
                ToList();
            if (users.Count == 1) {
                CurrentRwUser = users [0];
            } else {
                CurrentRwUser = new User { 
                    FacebookToken = CurrentMsUser.UserId, 
                    GoogleToken = "test",
                    TwitterToken = "test",
                    MicrosoftToken = "test",
                    Email = "test@gmail.com",
                    FacebookId = App.FacebookProvider.GetCurrentUserId (),
                    Name = App.FacebookProvider.GetCurrentUserName ()
                };
                await InsertUserAsync (CurrentRwUser);
                await SyncAsync();
            }
        } catch (Exception ex) {
            Debug.WriteLine ("CreateOrRetrieveAppUser failed: {0}", ex.Message);
        }
    }).ConfigureAwait(continueOnCapturedContext:false);
}

It appears that that variable is thread local, which is why its value is only accessible in your main thread. 看来该变量是线程局部的,这就是为什么只能在您的主线程中访问其值的原因。

You should grab the value of that variable in your main thread before moving to the background thread to avoid this problem. 为避免出现此问题,应在移至后台线程之前在主线程中获取该变量的值。

public async Task CreateOrRetrieveAppUserAsync()
{
    var userId = CurrentMsUser.UserId;
    await Task.Run (async () => {
    //...
    //use userId here
    });
}

Of course, given that you don't appear to have any long running CPU bound work, and all of the work that you have here is already asynchronous task based IO work, you should be able to simply remove the Task.Run call entirely, allowing what little CPU bound work you do have to run in the UI thread, without blocking it at all due to the long running operations all already being asynchronous. 当然,假设您似乎没有任何长时间运行的CPU绑定工作,并且这里的所有工作已经是基于异步任务的IO工作,那么您应该可以完全删除Task.Run调用,允许您在UI线程中运行几乎不需要 CPU约束的工作,而由于长时间运行的操作已经是异步的,因此根本不会阻塞它。

Oh, and since you only need the very first item of usersCollection you should use First , not ToList , to avoid materializing the entire result set into memory. 哦,由于只需要usersCollection第一项, usersCollection应使用First而不是ToList ,以避免将整个结果集具体化到内存中。 You should also perform that First and your filtering before calling ToCollectionAsync to, if at all possible, do all of this filtering through the query provider rather than materializing the entire collection into your application. 您还应该调用ToCollectionAsync 之前执行“ First过滤并在可能的情况下通过查询提供程序执行所有此过滤,而不是将整个集合具体化到您的应用程序中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM