C# NSAutoReleasePool和异步函数

C# NSAutoReleasePool和异步函数,c#,cocoa,monomac,C#,Cocoa,Monomac,我的程序中有一个函数,可以创建新的小部件来表示数据,但是每当创建一个小部件时,我都会收到很多“自动释放,没有NSAutoReleasePool”错误消息。由于NSAutoReleasePool应该在主线程上自动创建,因此我有一种迹象表明这些错误消息会出现,因为异步函数可能会创建我的线程 这是用来创建小部件以表示最新信息的函数。此函数经常被调用: private void CreateAndDisplayTvShowWidget (TvShow show) { va

我的程序中有一个函数,可以创建新的小部件来表示数据,但是每当创建一个小部件时,我都会收到很多“自动释放,没有NSAutoReleasePool”错误消息。由于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);
        }
    }
private static void ProcessResponse(字符串responseString,HttpWebRequest请求)
{
string requestUrl=request.Address.ToString();
if(requestUrl.Contains(ShowSearchTag)){
List searchResults=TvDbParser.ParseTvShowSearchResults(responseString);
TvShowSearchTimeoutClock.Enabled=false;
OnTvShowSearchComplete(搜索结果);
}else if(requestUrl.Contains(MirrorListTag)){
MirrorList=TvDbParser.ParseMirrorList(responseString);
SendRequestsOnHold();
}else if(requestUrl.Contains(TvShowBaseTag)){
TvShowBase showBase=TvDbParser.ParseTvShowBase(responseString);
OnTvshowBaseReceived(showBase);
}else if(requestUrl.Contains(ImagePathReqTag)){
字符串showID=GetShowIDFromImagePathRequest(请求URL);
TvShowImagePath imagePath=TvDbParser.ParseTvShowImagePath(showID,responseString);
ONTvshowImagePathReceived(imagePath);
}
}
当调用OntVShowBaseReceived(TvShow)事件时,会调用CreateAndDisplayTvShowWidget(TvShow show),也就是当我收到有关NSAutoReleasePool的错误消息时

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


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

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

如果您使用对象的自动释放功能,则只需要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也会在引擎盖上使用它们。

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

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

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

似乎仍然会出错。在添加新的小部件或更新小部件之前,我不会收到错误,因此当应用程序第一次启动并仅从保存文件创建小部件时,它可以与“using”语句配合使用……我意识到您是在辅助线程中创建小部件。我认为在主UI线程之外创建小部件不是一个好主意,因为Cocoa和其他任何UI框架一样都不是线程安全的。您可以通过使用
InvokeOnMainThread
方法()推迟在主UI线程上调用
CreateAndDisplayTvShowWidget
方法。好的,在决定是否应创建新小部件的函数中尝试了以下操作。。。InvokeOnMainThread(委托{CreateAndDisplayTvShowWidget(show);})。。。没有变化……我还能在这个问题上添加什么来帮助人们找出问题所在?我还是没办法找到答案。。。