我有以下电话(实际上比这多一些-这是这里要讨论的整体方法):

ThreadPool.QueueUserWorkItem(Database.Instance.RefreshEventData);
ThreadPool.QueueUserWorkItem(Database.Instance.RefreshLocationData);
ThreadPool.QueueUserWorkItem(Database.Instance.RefreshActData);


第一点是-这样调用WCF服务的方法可以吗?我尝试用菊花链将它们链接起来,结果一团糟。

上面调用的一种刷新方法的示例是(它们都遵循相同的模式,只是调用不同的服务并填充不同的表):

public void RefreshEventData (object state)
        {
            Console.WriteLine ("in RefreshEventData");
            var eservices = new AppServicesClient (new BasicHttpBinding (), new EndpointAddress (this.ServciceUrl));

            //default the delta to an old date so that if this is first run we get everything
            var eventsLastUpdated = DateTime.Now.AddDays (-100);

            try {
                eventsLastUpdated = (from s in GuideStar.Data.Database.Main.Table<GuideStar.Data.Event> ()
                    orderby s.DateUpdated descending
                    select s).ToList ().FirstOrDefault ().DateUpdated;

            } catch (Exception ex1) {
                Console.WriteLine (ex1.Message);
            }

            try {
                eservices.GetAuthorisedEventsWithExtendedDataAsync (this.User.Id, this.User.Password, eventsLastUpdated);
            } catch (Exception ex) {
                Console.WriteLine ("error updating events: " + ex.Message);
            }

            eservices.GetAuthorisedEventsWithExtendedDataCompleted += delegate(object sender, GetAuthorisedEventsWithExtendedDataCompletedEventArgs e) {

                try {

                    List<Event> newEvents = e.Result.ToList ();

                    GuideStar.Data.Database.Main.EventsAdded = e.Result.Count ();

                    lock (GuideStar.Data.Database.Main) {
                        GuideStar.Data.Database.Main.Execute ("BEGIN");

                        foreach (var s in newEvents) {

                            GuideStar.Data.Database.Main.InsertOrUpdateEvent (new GuideStar.Data.Event {
                                Name = s.Name,
                                DateAdded = s.DateAdded,
                                DateUpdated = s.DateUpdated,
                                Deleted = s.Deleted,
                                StartDate = s.StartDate,
                                Id = s.Id,
                                Lat = s.Lat,
                                Long = s.Long
                            });

                        }

                        GuideStar.Data.Database.Main.Execute ("COMMIT");
                        LocationsCount = 0;
                    }
                } catch (Exception ex) {
                    Console.WriteLine("error InsertOrUpdateEvent " + ex.Message);
                } finally {
                    OnDatabaseUpdateStepCompleted (EventArgs.Empty);
                }

            };
        }


OnDatabaseUpdateStepCompleted-只需在调用updateComplete计数器时对其进行迭代,并且当知道所有服务都恢复正常后,它将删除等待的微调器并继续运行该应用程序。

这第一次可以正常工作-但有时它与以下其中一项不兼容:http://monobin.com/__m6c83107d

我认为第一个问题是-这一切还好吗?我不习惯使用线程和锁,所以我正在为自己开拓新的领域。这样使用QueueUserWorkItem可以吗?在进行批量插入/更新之前,我应该使用锁吗?一个例子:

public void InsertOrUpdateEvent(Event festival){

            try {
                if (!festival.Deleted) {
                    Main.Insert(festival, "OR REPLACE");
                }else{
                    Main.Delete<Event>(festival);
                }
            } catch (Exception ex) {
                Console.WriteLine("InsertOrUpdateEvent failed: " + ex.Message);
            }

        }


然后下一个问题是-导致这些sqlite问题的我在做错什么?

w://

最佳答案

抱歉,没有具体答案,但有一些想法:

SqlLite甚至是线程安全的吗?我不确定-可能不是(对于包装器来说不是)。您可以锁定更全局的对象,这样就不会同时插入两个线程吗?

MT GC可能会变得有点过分热情,并在使用字符串之前将其释放。也许在插入过程中保留对它的本地引用?我曾经在视图控制器中发生过这种情况,我将它们放在一个数组中(特别是tabcontrollers),但是如果我没有在引用中保留成员变量,它们就会被GC。

您能以线程方式获取数据,然后将所有数据排队并插入单个线程中吗?无论如何,将Atleast作为测试。

10-01 15:57
查看更多