NSAutoReleasePool 和异步函数

发布于 2024-11-07 11:58:23 字数 2558 浏览 1 评论 0原文

我的程序中有一个函数可以创建新的小部件来表示数据,但是每当创建小部件时,我都会收到很多“AutoRelease with no NSAutoReleasePool in place”错误消息。由于 NSAutoReleasePool 应该在主线程上自动创建,因此我有一种暗示,这些错误消息的出现是因为异步函数可能会创建我的线程...

这是调用的函数,用于创建小部件来表示最新信息。这个函数经常被调用:

    private void CreateAndDisplayTvShowWidget (TvShow show)
    {
        var Widget = new TvShowWidgetController (show);
        Widget.OnRemoveWidget += ConfirmRemoveTvShow;

        Widget.View.SetFrameOrigin (new PointF (0, -150));
        Widget.View.SetFrameSize (new SizeF (ContentView.Frame.Width, 150));

        ContentView.AddSubview (Widget.View);
        show.ShowWidget = Widget;
    }

这个函数通常在这个异步函数返回时被调用:

    private static void WebRequestCallback (IAsyncResult result)
    {
        HttpWebRequest request = (HttpWebRequest)result.AsyncState;
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse (result);

        StreamReader responseStream = new StreamReader (response.GetResponseStream ());
        string responseString = responseStream.ReadToEnd ();
        responseStream.Close ();

        ProcessResponse (responseString, request);
    }

ProcessResponse (responseString, request) 看起来像这样:

    private static void ProcessResponse (string responseString, HttpWebRequest request)
    {
        string requestUrl = request.Address.ToString ();

        if (requestUrl.Contains (ShowSearchTag)) {
            List<TvShow> searchResults = TvDbParser.ParseTvShowSearchResults (responseString);
            TvShowSearchTimeoutClock.Enabled = false;
            OnTvShowSearchComplete (searchResults);
        } else if (requestUrl.Contains (MirrorListTag)) {
            MirrorList = TvDbParser.ParseMirrorList (responseString);
            SendRequestsOnHold ();
        } else if (requestUrl.Contains (TvShowBaseTag)) {
            TvShowBase showBase = TvDbParser.ParseTvShowBase (responseString);
            OnTvShowBaseRecieved (showBase);
        } else if (requestUrl.Contains (ImagePathReqTag)) {
            string showID = GetShowIDFromImagePathRequest (requestUrl);
            TvShowImagePath imagePath = TvDbParser.ParseTvShowImagePath (showID, responseString);
            OnTvShowImagePathRecieved (imagePath);
        }
    }

CreateAndDisplayTvShowWidget (TvShow show) 当事件 OnTvShowBaseRecieved (TvShow) 被调用时被调用,这是当我得到关于 NSAutoReleasePool 的大量错误消息...

最后两个函数是跨平台程序集的一部分,因此我不能在其中包含任何 MonoMac 特定的代码那里...

我从来没有为我的小部件调用任何自动释放或释放代码,所以我假设 MonoMac 绑定会自动执行此操作作为其垃圾收集的一部分?

I have a function in my program that creates new widgets to represent data, however whenever a widget is created i get alot of "AutoRelease with no NSAutoReleasePool in place" error messages. Since an NSAutoReleasePool should be automatically created on the main thread, I have an inkling that these error messages appear because an async function might create my threads...

This is the function called to create widgets to represent the latest information. This function is called pretty often:

    private void CreateAndDisplayTvShowWidget (TvShow show)
    {
        var Widget = new TvShowWidgetController (show);
        Widget.OnRemoveWidget += ConfirmRemoveTvShow;

        Widget.View.SetFrameOrigin (new PointF (0, -150));
        Widget.View.SetFrameSize (new SizeF (ContentView.Frame.Width, 150));

        ContentView.AddSubview (Widget.View);
        show.ShowWidget = Widget;
    }

This function is usually called when this async function returns:

    private static void WebRequestCallback (IAsyncResult result)
    {
        HttpWebRequest request = (HttpWebRequest)result.AsyncState;
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse (result);

        StreamReader responseStream = new StreamReader (response.GetResponseStream ());
        string responseString = responseStream.ReadToEnd ();
        responseStream.Close ();

        ProcessResponse (responseString, request);
    }

ProcessResponse (responseString, request) looks like this:

    private static void ProcessResponse (string responseString, HttpWebRequest request)
    {
        string requestUrl = request.Address.ToString ();

        if (requestUrl.Contains (ShowSearchTag)) {
            List<TvShow> searchResults = TvDbParser.ParseTvShowSearchResults (responseString);
            TvShowSearchTimeoutClock.Enabled = false;
            OnTvShowSearchComplete (searchResults);
        } else if (requestUrl.Contains (MirrorListTag)) {
            MirrorList = TvDbParser.ParseMirrorList (responseString);
            SendRequestsOnHold ();
        } else if (requestUrl.Contains (TvShowBaseTag)) {
            TvShowBase showBase = TvDbParser.ParseTvShowBase (responseString);
            OnTvShowBaseRecieved (showBase);
        } else if (requestUrl.Contains (ImagePathReqTag)) {
            string showID = GetShowIDFromImagePathRequest (requestUrl);
            TvShowImagePath imagePath = TvDbParser.ParseTvShowImagePath (showID, responseString);
            OnTvShowImagePathRecieved (imagePath);
        }
    }

CreateAndDisplayTvShowWidget (TvShow show) is called when the event OnTvShowBaseRecieved (TvShow) is called, which is when I get tons error messages regarding NSAutoReleasePool...

The last two functions are part of what is supposed to be a cross-platform assembly, so I can't have any MonoMac-specific code in there...

I never call any auto-release or release code for my widgets, so I assume that the MonoMac bindings does this automatically as part of its garbage collection?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蓬勃野心 2024-11-14 11:58:23

您可以在调用堆栈中的某个位置创建自动释放池,甚至可以在同一调用堆栈中使用多个嵌套的自动释放池。因此,您应该能够在异步入口函数中创建自动释放池。

You can create autorelease pools at point within the call stack, you can even have multiple nested autorelease pools with the same call stack. So you should be able to create your autorelease pools in the async entry functions.

南街九尾狐 2024-11-14 11:58:23

如果你使用对象的自动释放功能,你只需要一个 NSAutoreleasePool 。一个解决方案是围绕操作自动释放对象的代码创建一个 NSAutoreleasePool (在异步回调中)。

编辑:

您是否尝试过使用 NSAutoreleasePool 封装创建代码?由于这是您调用 MonoMac 代码的唯一位置,因此这应该可以解决问题。

private void CreateAndDisplayTvShowWidget (TvShow show)
{
    using(NSAutoreleasePool pool = new NSAutoreleasePool())
    {
        var Widget = new TvShowWidgetController (show);
        Widget.OnRemoveWidget += ConfirmRemoveTvShow;

        Widget.View.SetFrameOrigin (new PointF (0, -150));
        Widget.View.SetFrameSize (new SizeF (ContentView.Frame.Width, 150));

        ContentView.AddSubview (Widget.View);
        show.ShowWidget = Widget;
    }
}

请注意,即使您不直接使用自动释放的对象,在某些情况下,Cococa API 也会在后台使用它们。

You only need an NSAutoreleasePool if you use the auto-release features of objects. A solution is to create a NSAutoreleasePool around the code that manipulates auto-released objects (in the async callback).

Edit:

Have you tried to encapsulate the creation code with a NSAutoreleasePool ? As this is the only place where you call MonoMac code, this should solve the issue.

private void CreateAndDisplayTvShowWidget (TvShow show)
{
    using(NSAutoreleasePool pool = new NSAutoreleasePool())
    {
        var Widget = new TvShowWidgetController (show);
        Widget.OnRemoveWidget += ConfirmRemoveTvShow;

        Widget.View.SetFrameOrigin (new PointF (0, -150));
        Widget.View.SetFrameSize (new SizeF (ContentView.Frame.Width, 150));

        ContentView.AddSubview (Widget.View);
        show.ShowWidget = Widget;
    }
}

Note that even if you don't use auto-released objects directly, there are some case where the Cococa API use them udner the hood.

一个人练习一个人 2024-11-14 11:58:23

我遇到了类似的问题,问题出在response.GetResponseStream 上。我用......包围了这段代码

using (NSAutoreleasePool pool = new NSAutoreleasePool()) {
}

,这解决了我的问题。

I had a similar problem and it was the response.GetResponseStream that was the problem. I surrounded this code with...

using (NSAutoreleasePool pool = new NSAutoreleasePool()) {
}

... and that solved my problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文