Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 表单(IOS)动态构建列表视图项(ObservableCollection和Task.Factory)_C#_Ios_Objective C_Listview_Xamarin.forms - Fatal编程技术网

C# 表单(IOS)动态构建列表视图项(ObservableCollection和Task.Factory)

C# 表单(IOS)动态构建列表视图项(ObservableCollection和Task.Factory),c#,ios,objective-c,listview,xamarin.forms,C#,Ios,Objective C,Listview,Xamarin.forms,直截了当。 我的列表视图看起来像下面的xaml(不是100%相同,但应该足够详细) 我的内容。。。 这将绑定到我的视图模型,如下所示 private CancellationTokenSource cts = null private CancellationToken ct = CancellationToken.None private List<Task> tasks = new List<Task>() public ObservableCollection&l

直截了当。 我的列表视图看起来像下面的xaml(不是100%相同,但应该足够详细)

我的内容。。。
这将绑定到我的视图模型,如下所示

private CancellationTokenSource cts = null
private CancellationToken ct = CancellationToken.None
private List<Task> tasks = new List<Task>()
public ObservableCollection<T> Source = new ObservableCollection<T>()
public ObservableCollection<T> Result = new ObservableCollection<T>()
public string Query
private CancellationTokenSource cts=null
私有CancellationToken ct=CancellationToken.None
私有列表任务=新列表()
公共ObservableCollection源=新ObservableCollection()
公共ObservableCollection结果=新ObservableCollection()
公共字符串查询
它也有以下方法。这就是我的问题所在。该方法的行为应如下所示:

cts = new CancellationTokenSource();
ct = cts.Token;
//Result.Clear(); <-- I only changed this to
//Result = new ObservableCollection<T>(); // <-- this
// Outdated, currently using Result.RemoveAt(0); <-- See code edit
            cts.Cancel();
            cts.Dispose();
            Task.WaitAll(tasks.ToArray());
            tasks.Clear();
            cts = new CancellationTokenSource();
            ct = cts.Token;
            // Result.Clear();
            // Workaround see: https://stackoverflow.com/questions/48491781/xamarin-forms-ios-build-list-view-items-dynamically-observablecollection-and/48505622#48505622
            // Bug: https://bugzilla.xamarin.com/show_bug.cgi?id=59896
            // Result = new ObservableCollection<T>();
            while (Result.Count > 0) // <-- Temporary fix, low performance on > 10000 elements and may result the same error
                Result.RemoveAt(0);
            // Create background task
            tasks.Add(Task.Factory.StartNew(() =>
            {
                var validItems = Source.Where(c => ((ISearchQueryViewModel)c).SearchData.RegexContains(Query)).OrderByDescending(c => ((ISearchQueryViewModel)c).Aktive).ToList();
                if (ct.IsCancellationRequested)
                    return;
                for (int i = 0; i < validItems.Count; i++)
                {
                    if (ct.IsCancellationRequested)
                        return;
                    Result.Add(validItems[i]);
                    Thread.Sleep(25);
                }
            }, ct));
  • 从源代码获取所有元素(无论从何处获取)
  • 启动一个将在后台运行的任务(逐步构建列表,以减少在同一时间生成的listview项的数量,提高性能)
    • 因此,它会一步一步地将元素添加到结果中(在我的例子中,同时最多100个元素)
这是代码 注意:源已成功加载,元素在其中

            cts.Cancel();
            cts.Dispose();
            Task.WaitAll(tasks.ToArray());
            tasks.Clear();
            cts = new CancellationTokenSource();
            ct = cts.Token;
            Result.Clear();
            // Create background task
            tasks.Add(Task.Factory.StartNew(() =>
            {
                var validItems = Source.Where(c => ((ISearchQueryViewModel)c).SearchData.RegexContains(Query)).OrderByDescending(c => ((ISearchQueryViewModel)c).Aktive).ToList();
                if (ct.IsCancellationRequested)
                    return;
                var numberOfValidItemsToAdd = validItems.Count;
                var currentIndex = 0;
                while (numberOfValidItemsToAdd > 0)
                {
                    if (ct.IsCancellationRequested)
                        return;
                    var numberOfIndexes = 100;
                    if (numberOfValidItemsToAdd < 100)
                        numberOfIndexes = numberOfValidItemsToAdd;
                    for (int i = 0; i < numberOfIndexes; i++)
                    {
                        currentIndex++;
                        if (ct.IsCancellationRequested)
                            return;
                        Result.Add(validItems[i]);
                    }
                    numberOfValidItemsToAdd -= numberOfIndexes;
                    for (int i = 0; i < 100; i++)
                    {
                        if (ct.IsCancellationRequested)
                            return;
                        Thread.Sleep(50);
                    }
                }
            }, ct));
cts.Cancel();
cts.Dispose();
Task.WaitAll(tasks.ToArray());
任务。清除();
cts=新的CancellationTokenSource();
ct=cts.Token;
Result.Clear();
//创建后台任务
tasks.Add(Task.Factory.StartNew(()=>
{
var validItems=Source.Where(c=>((ISearchQueryViewModel)c).SearchData.RegexContains(Query)).OrderByDescending(c=>((ISearchQueryViewModel)c).akctive.ToList();
如果(ct.IsCancellationRequested)
返回;
var numberOfValidItemsToAdd=有效数据项计数;
var currentIndex=0;
while(numberOfValidItemsToAdd>0)
{
如果(ct.IsCancellationRequested)
返回;
var numberOfIndexes=100;
如果(NumberOfValidItemsToAdd100)
numberOfIndexes=numberOfValidItemsToAdd;
对于(int i=0;i
这导致了错误

未处理的异常:

Foundation.MonoTouchException:引发Objective-C异常。姓名: NSInternalInconsistencyException原因:无效更新:无效 节0中的行数。表中包含的行数 更新(1)后的现有节数必须等于 更新(1)之前该节中包含的行,加号或减号 从该节插入或删除的行数(插入1, 0)并加上或减去移入或移出的行数 该部分(0移入,0移出)。本机堆栈跟踪:0
CoreFoundation 0x00000001104da12b __异常预处理+171 1 libobjc.A.dylib 0x000000011dda6f41 objc_异常_抛出+48 2 CoreFoundation
0x00000001104df2f2+[NSException raise:格式:参数:][98 3
基金会0x000 000 011109D59 -[NSAssertionHandler handleFailureInMethod:对象:文件:行号:说明::+1934
UIKit 0x0000000114652209-[UITableView _endCellAnimationsWithContext:+19416 5 UIKit 0x000000011466d075-[UITableView EndUpdate]+75 6
MobileClient.iOS 0x000000010FD9F9 xamarin_dyn_objc_msgSend+2177???
0x000000013f12d452 0x0+5353165906

注意:这个答案已经过时了,如果我找到了一个答案,我会让你继续 解决这个问题的好方法

非常感谢@depchie

正是这只虫子。我是这样决定的:

cts = new CancellationTokenSource();
ct = cts.Token;
//Result.Clear(); <-- I only changed this to
//Result = new ObservableCollection<T>(); // <-- this
// Outdated, currently using Result.RemoveAt(0); <-- See code edit
            cts.Cancel();
            cts.Dispose();
            Task.WaitAll(tasks.ToArray());
            tasks.Clear();
            cts = new CancellationTokenSource();
            ct = cts.Token;
            // Result.Clear();
            // Workaround see: https://stackoverflow.com/questions/48491781/xamarin-forms-ios-build-list-view-items-dynamically-observablecollection-and/48505622#48505622
            // Bug: https://bugzilla.xamarin.com/show_bug.cgi?id=59896
            // Result = new ObservableCollection<T>();
            while (Result.Count > 0) // <-- Temporary fix, low performance on > 10000 elements and may result the same error
                Result.RemoveAt(0);
            // Create background task
            tasks.Add(Task.Factory.StartNew(() =>
            {
                var validItems = Source.Where(c => ((ISearchQueryViewModel)c).SearchData.RegexContains(Query)).OrderByDescending(c => ((ISearchQueryViewModel)c).Aktive).ToList();
                if (ct.IsCancellationRequested)
                    return;
                for (int i = 0; i < validItems.Count; i++)
                {
                    if (ct.IsCancellationRequested)
                        return;
                    Result.Add(validItems[i]);
                    Thread.Sleep(25);
                }
            }, ct));
链接:

上面的代码(在接下来的几次更新之后,问题中的代码应该是这样的^^^^^)

再次感谢您,祝您度过愉快的一天c:

编辑:

我还可以摆脱这种有线外观的方法,因此我的代码现在看起来完全像这样:

cts = new CancellationTokenSource();
ct = cts.Token;
//Result.Clear(); <-- I only changed this to
//Result = new ObservableCollection<T>(); // <-- this
// Outdated, currently using Result.RemoveAt(0); <-- See code edit
            cts.Cancel();
            cts.Dispose();
            Task.WaitAll(tasks.ToArray());
            tasks.Clear();
            cts = new CancellationTokenSource();
            ct = cts.Token;
            // Result.Clear();
            // Workaround see: https://stackoverflow.com/questions/48491781/xamarin-forms-ios-build-list-view-items-dynamically-observablecollection-and/48505622#48505622
            // Bug: https://bugzilla.xamarin.com/show_bug.cgi?id=59896
            // Result = new ObservableCollection<T>();
            while (Result.Count > 0) // <-- Temporary fix, low performance on > 10000 elements and may result the same error
                Result.RemoveAt(0);
            // Create background task
            tasks.Add(Task.Factory.StartNew(() =>
            {
                var validItems = Source.Where(c => ((ISearchQueryViewModel)c).SearchData.RegexContains(Query)).OrderByDescending(c => ((ISearchQueryViewModel)c).Aktive).ToList();
                if (ct.IsCancellationRequested)
                    return;
                for (int i = 0; i < validItems.Count; i++)
                {
                    if (ct.IsCancellationRequested)
                        return;
                    Result.Add(validItems[i]);
                    Thread.Sleep(25);
                }
            }, ct));
cts.Cancel();
cts.Dispose();
Task.WaitAll(tasks.ToArray());
任务。清除();
cts=新的CancellationTokenSource();
ct=cts.Token;
//Result.Clear();
//解决方法请参见:https://stackoverflow.com/questions/48491781/xamarin-forms-ios-build-list-view-items-dynamically-observablecollection-and/48505622#48505622
//错误:https://bugzilla.xamarin.com/show_bug.cgi?id=59896
//结果=新的ObservableCollection();
而(Result.Count>0)//10000个元素,可能会导致相同的错误
结果:RemoveAt(0);
//创建后台任务
tasks.Add(Task.Factory.StartNew(()=>
{
var validItems=Source.Where(c=>((ISearchQueryViewModel)c).SearchData.RegexContains(Query)).OrderByDescending(c=>((ISearchQueryViewModel)c).akctive.ToList();
如果(ct.IsCancellationRequested)
返回;
for(int i=0;iMyObservableCollection.Insert(MyObservableCollection.Count, myNewObject);
Result = new ObservableCollection<T>(GetNewList());