【问题标题】:Invalid cross-thread access Windows Azure无效的跨线程访问 Windows Azure
【发布时间】:2014-01-07 14:04:02
【问题描述】:

我正在使用 Windows Azure 移动服务开发一个 Windows Phone 8 应用程序。

我有以下代码:

private async void appBarButton1_Click(object sender, EventArgs e)
    {
        var table = App.MobileService.GetTable<ChatRoomOverview.chatrooms>();
        //TODO 
        List<ChatRoomOverview.chatrooms> ChatRooms = await table.Where(chat => chat.chatroomName == ChatroomName.Text).ToListAsync();
        if (ChatRooms.Count() < 1)
        {
            ChatRoomOverview.chatrooms ChatRoom = new ChatRoomOverview.chatrooms { chatroomName = ChatroomName.Text, Created = DateTime.Today.Date.ToString(), content = ChatRoomOverview.userName + "|:::|" + FirstPost.Text + "|::|::|", LastPost = FirstPost.Text + "|::|::|", tag1 = tag1.Text, tag2 = tag2.Text, tag3 = tag3.Text, isPrivate = isPrivateCheck.IsChecked.Value, userName = ChatRoomOverview.userName, Popular = "0" };

            await table.InsertAsync(ChatRoom);
            long tempID =ChatRoom.Id;
            await subscripeToNewChatRoom(tempID);

            NavigationService.Navigate(new Uri("/ChatRoomOverview.xaml", UriKind.Relative));
        }
        else
        {
            MessageBox.Show("This Chatroom is allready created go to Search and check it out :)", "Chatroom Exists!", MessageBoxButton.OK);
        }
    }

当用户想要创建聊天室时执行上述代码。一切都在这里工作。但是在我的应用程序的新迭代中,我想实现推送通知,因此我想使用订阅表。这是在 subscipeToNewChatRoom 函数中引入的。它的变量是在插入聊天室项目时给定的聊天室颁发的 ID。此值存在且正确。

    private System.Threading.Tasks.Task subscripeToNewChatRoom(long tempID)
    {
        ChatRoomOverview.Subscription Subscription = new ChatRoomOverview.Subscription { ContentID = Convert.ToInt32(tempID), userId = App.UserInfromationID };
        **ERROR** App.MobileService.GetTable<ChatRoomOverview.Subscription>().InsertAsync(Subscription);
        return null;
    }

然后执行上述代码以插入订阅。这段代码在代码中的其他地方工作,所以我不明白错误是什么。但是错误发生在我在代码中写入错误的地方。完整的例外情况在问题的底部。

所以我不明白为什么我会得到无效的跨线程访问?

额外 好的,在 Jaihind 答案和 cmets 的基础上,我想出了下面的代码。我现在可以看到我与之交互的表获得了正确的数据。 Buuut我仍然得到例外。

private async void bwSubscription_DoWork(object sender, DoWorkEventArgs e)
    {
        List<object> genericlist = e.Argument as List<object>;

        var table = await App.MobileService.GetTable<ChatRoomOverview.chatrooms>();
        //List<ChatRoomOverview.chatrooms> ChatRooms = table.Where(chat => chat.chatroomName == ChatroomName.Text)

        //table.InsertAsync(ChatRoom);
        ChatRoomOverview.chatrooms chat = (ChatRoomOverview.chatrooms)genericlist[0];
        //var ChatRoom = table.Where(chatting => chatting.chatroomName == chat.chatroomName).ToListAsync();

        long tempID = chat.Id;

        ChatRoomOverview.Subscription Subscription = new ChatRoomOverview.Subscription { ContentID = tempID, userId = App.UserInfromationID };
        await App.MobileService.GetTable<ChatRoomOverview.Subscription>().InsertAsync(Subscription);
    }

但是在插入try/catch时,为了处理没有发生的异常,项目不会被插入到azure表中。

工作解决方案

    private async void bwSubscription_DoWork(object sender, DoWorkEventArgs e)
    {
        bool subscriped = false;
        List<object> genericlist = e.Argument as List<object>;

        var table = App.MobileService.GetTable<ChatRoomOverview.chatrooms>();
        //List<ChatRoomOverview.chatrooms> ChatRooms = table.Where(chat => chat.chatroomName == ChatroomName.Text)

        //table.InsertAsync(ChatRoom);
        ChatRoomOverview.chatrooms chat = (ChatRoomOverview.chatrooms)genericlist[0];
        //var ChatRoom = table.Where(chatting => chatting.chatroomName == chat.chatroomName).ToListAsync();

        long tempID = chat.Id;
        while (!subscriped)
        {
            try
            {
                ChatRoomOverview.Subscription Subscription = new ChatRoomOverview.Subscription { ContentID = tempID, userId = App.UserInfromationID , Notifications = 0};
                await App.MobileService.GetTable<ChatRoomOverview.Subscription>().InsertAsync(Subscription);
            }
            catch
            {

            }
            List<ChatRoomOverview.Subscription> subscript = await App.MobileService.GetTable<ChatRoomOverview.Subscription>().Where(subs => subs.ContentID == tempID && subs.userId == App.UserInfromationID && subs.Notifications == 0).ToListAsync();
            if (subscript.Count > 0)
            {
                ChatRoomOverview.userName = "";
                subscriped = true;
            }
            else
            {
                subscriped = false;
            }
        }

    }

我的例外情况全文

  • $exception {System.UnauthorizedAccessException: 无效的跨线程访问。 在 MS.Internal.XcpImports.CheckThread() 在 MS.Internal.XcpImports.MessageBox_ShowCore(字符串 messageBoxText,字符串标题,UInt32 类型) 在 System.Windows.MessageBox.ShowCore(字符串 messageBoxText,字符串标题,MessageBoxButton 按钮) 在 System.Windows.MessageBox.Show(字符串 messageBoxText) 在 ChatRoom.App.CurrentChannel_ShellToastNotificationReceived(对象发送者,NotificationEventArgs e) 在 Microsoft.Phone.Notification.ShellObjectChannelInternals.OnNotificationReceived(IntPtr blob,UInt32 blobSize) 在 Microsoft.Phone.Notification.ShellObjectChannelInternals.ChannelHandler(UInt32 事件类型,IntPtr blob1,UInt32 blobSize1,IntPtr blob2,UInt32 blobSize2) 在 Microsoft.Phone.Notification.HttpNotificationChannel.Dispatch(对象 threadContext) 在 System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(对象状态) 在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback 回调,对象状态,布尔值 preserveSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback 回调,对象状态,布尔值 preserveSyncCtx) 在 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()} System.Exception {System.UnauthorizedAccessException}

【问题讨论】:

  • 我不明白这与 Azure 有什么关系。异常中的调用堆栈清楚地表明已要求后台线程显示消息框。必须从 GUI 线程显示消息框。

标签: c# multithreading azure windows-phone-8 azure-mobile-services


【解决方案1】:

希望这会对您有所帮助。

private subscripeToNewChatRoom(long tempID)
            {
                ChatRoomOverview.Subscription Subscription = new ChatRoomOverview.Subscription { ContentID = Convert.ToInt32(tempID), userId = App.UserInfromationID };
         Dispatcher.BeginInvoke(() =>
                        {
        App.MobileService.GetTable<ChatRoomOverview.Subscription>().InsertAsync(Subscription);
                        });

                return null;
            }

【讨论】:

  • 不幸的是,我仍然收到错误消息,我阅读了有关此解决方案的信息,但理解它与 UI 存在问题?我试过了,但没有解决问题。
  • @JTIM 在 appBarButton1_Click 事件中使用 Dispatcher。
  • 我删除了 subscripeToNewChatRoom 函数。并将代码向上移动到 appBarButton1_Click 事件中,发生同样的错误:/
  • @JTIM 使用后台工作人员而不是调度程序。这是链接msdn.microsoft.com/en-us/library/windowsphone/develop/…
  • 那我试试。但我不明白为什么这是某个地方而不是其他地方的问题?
【解决方案2】:

工作解决方案

private async void bwSubscription_DoWork(object sender, DoWorkEventArgs e)
{
    bool subscriped = false;
    List<object> genericlist = e.Argument as List<object>;

    var table = App.MobileService.GetTable<ChatRoomOverview.chatrooms>();
    //List<ChatRoomOverview.chatrooms> ChatRooms = table.Where(chat => chat.chatroomName == ChatroomName.Text)

    //table.InsertAsync(ChatRoom);
    ChatRoomOverview.chatrooms chat = (ChatRoomOverview.chatrooms)genericlist[0];
    //var ChatRoom = table.Where(chatting => chatting.chatroomName == chat.chatroomName).ToListAsync();

    long tempID = chat.Id;
    while (!subscriped)
    {
        try
        {
            ChatRoomOverview.Subscription Subscription = new ChatRoomOverview.Subscription { ContentID = tempID, userId = App.UserInfromationID , Notifications = 0};
            await App.MobileService.GetTable<ChatRoomOverview.Subscription>().InsertAsync(Subscription);
        }
        catch
        {

        }
        List<ChatRoomOverview.Subscription> subscript = await App.MobileService.GetTable<ChatRoomOverview.Subscription>().Where(subs => subs.ContentID == tempID && subs.userId == App.UserInfromationID && subs.Notifications == 0).ToListAsync();
        if (subscript.Count > 0)
        {
            ChatRoomOverview.userName = "";
            subscriped = true;
        }
        else
        {
            subscriped = false;
        }
    }

}

【讨论】:

    【解决方案3】:

    不要尝试从后台线程显示用户界面元素。调用堆栈清楚地表明这是您想要做的。

    QueueUserWorkItem 表示这是来自后台线程的调用堆栈。然后我们看到MessageBox.Show() 正在被调用。这将在桌面应用程序或与 azure 没有任何联系的应用程序中引发相同的异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-04
      • 1970-01-01
      相关资源
      最近更新 更多