1

我的程序中有一个函数可以创建新的小部件来表示数据,但是每当创建小部件时,我都会收到很多“没有 NSAutoReleasePool 的 AutoRelease”错误消息。由于 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);
        }
    }

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

最后两个函数是应该是跨平台程序集的一部分,所以我不能在那里有任何 MonoMac 特定的代码......

我从不为我的小部件调用任何自动发布或发布代码,所以我假设 MonoMac 绑定会自动将其作为其垃圾收集的一部分?

4

3 回答 3

0

您可以在调用堆栈中的某个位置创建自动释放池,甚至可以拥有多个嵌套的自动释放池和相同的调用堆栈。所以你应该能够在异步入口函数中创建你的自动释放池。

于 2011-05-15T04:05:52.597 回答
0

我有一个类似的问题,问题是 response.GetResponseStream。我用...包围了这段代码

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

...这解决了我的问题。

于 2013-07-09T14:11:57.893 回答
0

如果你使用对象的自动释放特性,你只需要一个 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 也会在底层使用它们。

于 2011-05-17T23:07:23.897 回答